/**
 * 🔥 성능 최적화: 데이터플로우 설정 캐싱 시스템
 *
 * 버튼별 제어관리 설정을 메모리에 캐시하여
 * 1ms 수준의 즉시 응답을 제공합니다.
 */

import { ButtonDataflowConfig } from "@/types/screen";
import { apiClient } from "@/lib/api/client";

export interface CachedDataflowConfig {
  config: ButtonDataflowConfig;
  timestamp: number;
  hits: number; // 캐시 히트 횟수 (통계용)
}

export interface CacheMetrics {
  totalRequests: number;
  cacheHits: number;
  cacheMisses: number;
  hitRate: number; // 히트율 (%)
  averageResponseTime: number; // 평균 응답 시간 (ms)
}

/**
 * 🔥 L1 메모리 캐시 (1ms 응답)
 *
 * - TTL: 5분 (300초)
 * - 자동 만료 처리
 * - 성능 지표 수집
 */
export class DataflowConfigCache {
  private memoryCache = new Map<string, CachedDataflowConfig>();
  private readonly TTL = 5 * 60 * 1000; // 5분 TTL
  private metrics: CacheMetrics = {
    totalRequests: 0,
    cacheHits: 0,
    cacheMisses: 0,
    hitRate: 0,
    averageResponseTime: 0,
  };

  /**
   * 🔥 버튼별 제어관리 설정 조회 (캐시 우선)
   */
  async getConfig(buttonId: string): Promise<ButtonDataflowConfig | null> {
    const startTime = performance.now();
    this.metrics.totalRequests++;

    const cacheKey = `button_dataflow_${buttonId}`;

    try {
      // L1: 메모리 캐시 확인 (1ms)
      if (this.memoryCache.has(cacheKey)) {
        const cached = this.memoryCache.get(cacheKey)!;

        // TTL 확인
        if (Date.now() - cached.timestamp < this.TTL) {
          cached.hits++;
          this.metrics.cacheHits++;
          this.updateHitRate();

          const responseTime = performance.now() - startTime;
          this.updateAverageResponseTime(responseTime);

          console.log(`⚡ Cache hit: ${buttonId} (${responseTime.toFixed(2)}ms)`);
          return cached.config;
        } else {
          // TTL 만료된 캐시 제거
          this.memoryCache.delete(cacheKey);
        }
      }

      // L2: 서버에서 로드 (100-300ms)
      console.log(`🌐 Loading from server: ${buttonId}`);
      const serverConfig = await this.loadFromServer(buttonId);

      // 캐시에 저장
      if (serverConfig) {
        this.memoryCache.set(cacheKey, {
          config: serverConfig,
          timestamp: Date.now(),
          hits: 1,
        });
      }

      this.metrics.cacheMisses++;
      this.updateHitRate();

      const responseTime = performance.now() - startTime;
      this.updateAverageResponseTime(responseTime);

      console.log(`📡 Server response: ${buttonId} (${responseTime.toFixed(2)}ms)`);
      return serverConfig;
    } catch (error) {
      console.error(`❌ Failed to get config for button ${buttonId}:`, error);

      const responseTime = performance.now() - startTime;
      this.updateAverageResponseTime(responseTime);

      return null;
    }
  }

  /**
   * 🔥 서버에서 설정 로드
   */
  private async loadFromServer(buttonId: string): Promise<ButtonDataflowConfig | null> {
    try {
      const response = await apiClient.get(`/api/button-dataflow/config/${buttonId}`);

      if (response.data.success) {
        return response.data.data as ButtonDataflowConfig;
      }

      return null;
    } catch (error) {
      // 404는 정상 상황 (설정이 없는 버튼)
      if (error.response?.status === 404) {
        return null;
      }
      throw error;
    }
  }

  /**
   * 🔥 설정 업데이트 (캐시 무효화)
   */
  async updateConfig(buttonId: string, config: ButtonDataflowConfig): Promise<void> {
    const cacheKey = `button_dataflow_${buttonId}`;

    try {
      // 서버에 저장
      await apiClient.put(`/api/button-dataflow/config/${buttonId}`, config);

      // 캐시 업데이트
      this.memoryCache.set(cacheKey, {
        config,
        timestamp: Date.now(),
        hits: 0,
      });

      console.log(`💾 Config updated: ${buttonId}`);
    } catch (error) {
      console.error(`❌ Failed to update config for button ${buttonId}:`, error);
      throw error;
    }
  }

  /**
   * 🔥 특정 버튼 캐시 무효화
   */
  invalidateCache(buttonId: string): void {
    const cacheKey = `button_dataflow_${buttonId}`;
    this.memoryCache.delete(cacheKey);
    console.log(`🗑️ Cache invalidated: ${buttonId}`);
  }

  /**
   * 🔥 전체 캐시 무효화
   */
  clearAllCache(): void {
    this.memoryCache.clear();
    console.log(`🗑️ All cache cleared`);
  }

  /**
   * 🔥 관계도별 캐시 무효화 (관계도가 수정된 경우)
   */
  invalidateDiagramCache(diagramId: number): void {
    let invalidatedCount = 0;

    for (const [key, cached] of this.memoryCache.entries()) {
      if (cached.config.selectedDiagramId === diagramId) {
        this.memoryCache.delete(key);
        invalidatedCount++;
      }
    }

    if (invalidatedCount > 0) {
      console.log(`🗑️ Invalidated ${invalidatedCount} caches for diagram ${diagramId}`);
    }
  }

  /**
   * 🔥 캐시 통계 조회
   */
  getMetrics(): CacheMetrics {
    return { ...this.metrics };
  }

  /**
   * 🔥 상세 캐시 정보 조회 (디버깅용)
   */
  getCacheInfo(): Array<{
    buttonId: string;
    config: ButtonDataflowConfig;
    age: number; // 캐시된지 몇 분 경과
    hits: number;
    ttlRemaining: number; // 남은 TTL (초)
  }> {
    const now = Date.now();
    const result: Array<any> = [];

    for (const [key, cached] of this.memoryCache.entries()) {
      const buttonId = key.replace("button_dataflow_", "");
      const age = Math.floor((now - cached.timestamp) / 1000 / 60); // 분
      const ttlRemaining = Math.max(0, Math.floor((this.TTL - (now - cached.timestamp)) / 1000)); // 초

      result.push({
        buttonId,
        config: cached.config,
        age,
        hits: cached.hits,
        ttlRemaining,
      });
    }

    return result.sort((a, b) => b.hits - a.hits); // 히트 수 기준 내림차순
  }

  /**
   * 🔥 TTL 만료된 캐시 정리 (주기적 호출)
   */
  cleanupExpiredCache(): number {
    const now = Date.now();
    let cleanedCount = 0;

    for (const [key, cached] of this.memoryCache.entries()) {
      if (now - cached.timestamp >= this.TTL) {
        this.memoryCache.delete(key);
        cleanedCount++;
      }
    }

    if (cleanedCount > 0) {
      console.log(`🧹 Cleaned up ${cleanedCount} expired cache entries`);
    }

    return cleanedCount;
  }

  /**
   * 히트율 업데이트
   */
  private updateHitRate(): void {
    this.metrics.hitRate =
      this.metrics.totalRequests > 0 ? (this.metrics.cacheHits / this.metrics.totalRequests) * 100 : 0;
  }

  /**
   * 평균 응답 시간 업데이트 (이동 평균)
   */
  private updateAverageResponseTime(responseTime: number): void {
    if (this.metrics.averageResponseTime === 0) {
      this.metrics.averageResponseTime = responseTime;
    } else {
      // 이동 평균 (기존 90% + 새로운 값 10%)
      this.metrics.averageResponseTime = this.metrics.averageResponseTime * 0.9 + responseTime * 0.1;
    }
  }
}

// 🔥 전역 싱글톤 인스턴스
export const dataflowConfigCache = new DataflowConfigCache();

// 🔥 5분마다 만료된 캐시 정리
if (typeof window !== "undefined") {
  setInterval(
    () => {
      dataflowConfigCache.cleanupExpiredCache();
    },
    5 * 60 * 1000,
  ); // 5분
}

// 🔥 개발 모드에서 캐시 정보를 전역 객체에 노출
if (typeof window !== "undefined" && process.env.NODE_ENV === "development") {
  (window as any).dataflowCache = {
    getMetrics: () => dataflowConfigCache.getMetrics(),
    getCacheInfo: () => dataflowConfigCache.getCacheInfo(),
    clearCache: () => dataflowConfigCache.clearAllCache(),
  };
}
