/**
 * 공통 코드 캐시 시스템
 * 자주 사용되는 공통 코드들을 메모리에 캐싱하여 성능을 향상시킵니다.
 */

import { commonCodeApi } from "@/lib/api/commonCode";

interface CacheEntry {
  data: any;
  timestamp: number;
  expiry: number;
}

class CodeCache {
  private cache = new Map<string, CacheEntry>();
  private defaultTTL = 5 * 60 * 1000; // 5분

  /**
   * 캐시에 데이터 저장
   */
  set(key: string, data: any, ttl?: number): void {
    const expiry = ttl || this.defaultTTL;
    const entry: CacheEntry = {
      data,
      timestamp: Date.now(),
      expiry,
    };
    this.cache.set(key, entry);
  }

  /**
   * 캐시에서 데이터 조회
   */
  get(key: string): any | null {
    const entry = this.cache.get(key);
    if (!entry) {
      return null;
    }

    // TTL 체크
    if (Date.now() - entry.timestamp > entry.expiry) {
      this.cache.delete(key);
      return null;
    }

    return entry.data;
  }

  /**
   * 캐시에서 데이터 삭제
   */
  delete(key: string): boolean {
    return this.cache.delete(key);
  }

  /**
   * 모든 캐시 삭제
   */
  clear(): void {
    this.cache.clear();
  }

  /**
   * 만료된 캐시 정리
   */
  cleanup(): void {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > entry.expiry) {
        this.cache.delete(key);
      }
    }
  }

  /**
   * 캐시 상태 조회
   */
  getStats(): { size: number; keys: string[] } {
    return {
      size: this.cache.size,
      keys: Array.from(this.cache.keys()),
    };
  }

  /**
   * 공통 코드 캐시 키 생성
   */
  createCodeKey(category: string, companyCode?: string): string {
    return `code:${category}:${companyCode || "*"}`;
  }

  /**
   * 여러 코드 카테고리를 배치로 미리 로딩
   */
  async preloadCodes(categories: string[]): Promise<void> {
    // console.log(`🔄 코드 배치 로딩 시작: ${categories.join(", ")}`);
    
    const promises = categories.map(async (category) => {
      try {
        const response = await commonCodeApi.codes.getList(category, { isActive: true });
        if (response.success && response.data) {
          const cacheKey = this.createCodeKey(category);
          this.set(cacheKey, response.data, this.defaultTTL);
          // console.log(`✅ 코드 로딩 완료: ${category} (${response.data.length}개)`);
        }
      } catch (error) {
        console.error(`❌ 코드 로딩 실패: ${category}`, error);
      }
    });

    await Promise.all(promises);
    // console.log(`✅ 코드 배치 로딩 완료: ${categories.length}개 카테고리`);
  }

  /**
   * 코드를 동기적으로 조회 (캐시에서만)
   */
  getCodeSync(category: string, companyCode?: string): any[] | null {
    const cacheKey = this.createCodeKey(category, companyCode);
    return this.get(cacheKey);
  }

  /**
   * 코드를 비동기적으로 조회 (캐시 미스 시 API 호출)
   */
  async getCodeAsync(category: string, companyCode?: string): Promise<any[]> {
    const cached = this.getCodeSync(category, companyCode);
    if (cached) {
      return cached;
    }

    try {
      const response = await commonCodeApi.codes.getList(category, { isActive: true });
      if (response.success && response.data) {
        const cacheKey = this.createCodeKey(category, companyCode);
        this.set(cacheKey, response.data, this.defaultTTL);
        return response.data;
      }
    } catch (error) {
      console.error(`❌ 코드 조회 실패: ${category}`, error);
    }

    return [];
  }

  /**
   * 캐시 정보 조회 (성능 메트릭용)
   */
  getCacheInfo(): {
    size: number;
    keys: string[];
    totalMemoryUsage: number;
    hitRate?: number;
  } {
    const stats = this.getStats();
    
    // 메모리 사용량 추정 (대략적)
    let totalMemoryUsage = 0;
    for (const [key, entry] of this.cache.entries()) {
      // 키 크기 + 데이터 크기 추정
      totalMemoryUsage += key.length * 2; // 문자열은 UTF-16이므로 2바이트
      if (Array.isArray(entry.data)) {
        totalMemoryUsage += entry.data.length * 100; // 각 항목당 대략 100바이트로 추정
      } else {
        totalMemoryUsage += JSON.stringify(entry.data).length * 2;
      }
    }

    return {
      ...stats,
      totalMemoryUsage,
    };
  }

  /**
   * 특정 카테고리의 캐시 무효화
   */
  invalidate(category: string, companyCode?: string): boolean {
    const cacheKey = this.createCodeKey(category, companyCode);
    return this.delete(cacheKey);
  }
}

// 싱글톤 인스턴스 생성
const codeCache = new CodeCache();

// 주기적으로 만료된 캐시 정리 (10분마다)
if (typeof window !== "undefined") {
  setInterval(
    () => {
      codeCache.cleanup();
    },
    10 * 60 * 1000,
  );
}

export default codeCache;
export { CodeCache, codeCache };
