"use client";

import { LayoutRegistry } from "../LayoutRegistry";

/**
 * 자동 디스커버리 옵션
 */
export interface AutoDiscoveryOptions {
  /** 스캔할 디렉토리 패턴 */
  pattern?: string;
  /** 개발 모드에서 상세 로그 출력 */
  verbose?: boolean;
  /** 에러 시 계속 진행할지 여부 */
  continueOnError?: boolean;
  /** 최대 대기 시간 (ms) */
  timeout?: number;
}

/**
 * 레이아웃 모듈 정보
 */
export interface LayoutModuleInfo {
  path: string;
  id: string;
  name: string;
  loaded: boolean;
  error?: Error;
  timestamp: number;
}

/**
 * 자동 디스커버리 결과
 */
export interface DiscoveryResult {
  success: boolean;
  totalFound: number;
  successfullyLoaded: number;
  failed: number;
  modules: LayoutModuleInfo[];
  errors: Error[];
  duration: number;
}

/**
 * 레이아웃 자동 디스커버리 클래스
 */
export class LayoutAutoDiscovery {
  private static instance: LayoutAutoDiscovery;
  private discoveryResults: DiscoveryResult[] = [];
  private isDiscovering = false;

  static getInstance(): LayoutAutoDiscovery {
    if (!this.instance) {
      this.instance = new LayoutAutoDiscovery();
    }
    return this.instance;
  }

  /**
   * 레이아웃 자동 디스커버리 실행
   */
  async discover(options: AutoDiscoveryOptions = {}): Promise<DiscoveryResult> {
    const startTime = Date.now();
    const {
      pattern = "./**/*LayoutRenderer.tsx",
      verbose = process.env.NODE_ENV === "development",
      continueOnError = true,
      timeout = 10000,
    } = options;

    if (this.isDiscovering) {
      throw new Error("디스커버리가 이미 진행 중입니다.");
    }

    this.isDiscovering = true;

    try {
      if (verbose) {
        console.log("🔍 레이아웃 자동 디스커버리 시작...");
        console.log(`📁 스캔 패턴: ${pattern}`);
      }

      const modules: LayoutModuleInfo[] = [];
      const errors: Error[] = [];

      // 현재는 정적 import를 사용 (Vite/Next.js 환경에서)
      const layoutModules = await this.discoverLayoutModules(pattern);

      for (const [path, moduleFactory] of Object.entries(layoutModules)) {
        const moduleInfo: LayoutModuleInfo = {
          path,
          id: this.extractLayoutId(path),
          name: this.extractLayoutName(path),
          loaded: false,
          timestamp: Date.now(),
        };

        try {
          // 모듈 로드 시도
          await this.loadLayoutModule(moduleFactory, moduleInfo);
          moduleInfo.loaded = true;

          if (verbose) {
            console.log(`✅ 로드 성공: ${moduleInfo.name} (${moduleInfo.id})`);
          }
        } catch (error) {
          const err = error as Error;
          moduleInfo.error = err;
          errors.push(err);

          if (verbose) {
            console.error(`❌ 로드 실패: ${moduleInfo.name}`, err);
          }

          if (!continueOnError) {
            throw err;
          }
        }

        modules.push(moduleInfo);
      }

      const result: DiscoveryResult = {
        success: errors.length === 0,
        totalFound: modules.length,
        successfullyLoaded: modules.filter((m) => m.loaded).length,
        failed: errors.length,
        modules,
        errors,
        duration: Date.now() - startTime,
      };

      this.discoveryResults.push(result);

      if (verbose) {
        this.logDiscoveryResult(result);
      }

      return result;
    } finally {
      this.isDiscovering = false;
    }
  }

  /**
   * 레이아웃 모듈 발견
   */
  private async discoverLayoutModules(pattern: string): Promise<Record<string, () => Promise<any>>> {
    try {
      // Vite의 import.meta.glob 사용
      if (typeof import.meta !== "undefined" && import.meta.glob) {
        return import.meta.glob(pattern, { eager: false });
      }

      // Next.js의 경우 또는 fallback
      return await this.discoverModulesViaWebpack(pattern);
    } catch (error) {
      console.warn("자동 디스커버리 실패, 수동 import로 전환:", error);
      return {};
    }
  }

  /**
   * Webpack 기반 모듈 디스커버리 (Next.js용)
   */
  private async discoverModulesViaWebpack(pattern: string): Promise<Record<string, () => Promise<any>>> {
    // Next.js 환경에서는 require.context 사용
    if (typeof require !== "undefined" && require.context) {
      const context = require.context("../layouts", true, /.*LayoutRenderer\.tsx$/);
      const modules: Record<string, () => Promise<any>> = {};

      context.keys().forEach((key: string) => {
        modules[key] = () => Promise.resolve(context(key));
      });

      return modules;
    }

    return {};
  }

  /**
   * 레이아웃 모듈 로드
   */
  private async loadLayoutModule(moduleFactory: () => Promise<any>, moduleInfo: LayoutModuleInfo): Promise<void> {
    const module = await moduleFactory();

    // default export가 있는 경우
    if (module.default && typeof module.default.registerSelf === "function") {
      module.default.registerSelf();
      return;
    }

    // named export 중에 레이아웃 렌더러가 있는 경우
    for (const [exportName, exportValue] of Object.entries(module)) {
      if (exportValue && typeof (exportValue as any).registerSelf === "function") {
        (exportValue as any).registerSelf();
        return;
      }
    }

    throw new Error(`레이아웃 렌더러를 찾을 수 없습니다: ${moduleInfo.path}`);
  }

  /**
   * 경로에서 레이아웃 ID 추출
   */
  private extractLayoutId(path: string): string {
    const match = path.match(/\/([^/]+)LayoutRenderer\.tsx$/);
    return match ? match[1].toLowerCase() : "unknown";
  }

  /**
   * 경로에서 레이아웃 이름 추출
   */
  private extractLayoutName(path: string): string {
    const id = this.extractLayoutId(path);
    return id.charAt(0).toUpperCase() + id.slice(1) + " Layout";
  }

  /**
   * 디스커버리 결과 로그 출력
   */
  private logDiscoveryResult(result: DiscoveryResult): void {
    console.group("📊 레이아웃 디스커버리 결과");
    console.log(`⏱️ 소요 시간: ${result.duration}ms`);
    console.log(`📦 발견된 모듈: ${result.totalFound}개`);
    console.log(`✅ 성공적으로 로드: ${result.successfullyLoaded}개`);
    console.log(`❌ 실패: ${result.failed}개`);

    if (result.modules.length > 0) {
      console.table(
        result.modules.map((m) => ({
          ID: m.id,
          Name: m.name,
          Loaded: m.loaded ? "✅" : "❌",
          Path: m.path,
        })),
      );
    }

    if (result.errors.length > 0) {
      console.group("❌ 오류 상세:");
      result.errors.forEach((error) => console.error(error));
      console.groupEnd();
    }

    console.groupEnd();
  }

  /**
   * 이전 디스커버리 결과 조회
   */
  getDiscoveryHistory(): DiscoveryResult[] {
    return [...this.discoveryResults];
  }

  /**
   * 통계 정보 조회
   */
  getStats(): { totalAttempts: number; successRate: number; avgDuration: number } {
    const attempts = this.discoveryResults.length;
    const successful = this.discoveryResults.filter((r) => r.success).length;
    const avgDuration = attempts > 0 ? this.discoveryResults.reduce((sum, r) => sum + r.duration, 0) / attempts : 0;

    return {
      totalAttempts: attempts,
      successRate: attempts > 0 ? (successful / attempts) * 100 : 0,
      avgDuration: Math.round(avgDuration),
    };
  }
}

/**
 * 편의 함수: 레이아웃 자동 디스커버리 실행
 */
export async function discoverLayouts(options?: AutoDiscoveryOptions): Promise<DiscoveryResult> {
  const discovery = LayoutAutoDiscovery.getInstance();
  return discovery.discover(options);
}

/**
 * 편의 함수: 통계 정보 조회
 */
export function getDiscoveryStats() {
  const discovery = LayoutAutoDiscovery.getInstance();
  return discovery.getStats();
}
