"use client";

import React from "react";
import {
  ComponentDefinition,
  ComponentCategory,
  ComponentRegistryEvent,
  ComponentSearchOptions,
  ComponentStats,
  ComponentAutoDiscoveryOptions,
  ComponentDiscoveryResult,
} from "@/types/component";
import type { WebType } from "@/types/screen";

/**
 * 컴포넌트 레지스트리 클래스
 * 동적으로 컴포넌트를 등록, 관리, 조회할 수 있는 중앙 레지스트리
 * 레이아웃 시스템과 동일한 패턴으로 설계
 */
export class ComponentRegistry {
  private static components = new Map<string, ComponentDefinition>();
  private static eventListeners: Array<(event: ComponentRegistryEvent) => void> = [];

  /**
   * 컴포넌트 등록
   */
  static registerComponent(definition: ComponentDefinition): void {
    // 유효성 검사
    const validation = this.validateComponentDefinition(definition);
    if (!validation.isValid) {
      throw new Error(`컴포넌트 등록 실패 (${definition.id}): ${validation.errors.join(", ")}`);
    }

    // 중복 등록 체크 (기존 정의를 덮어씀)

    // 타임스탬프 추가
    const enhancedDefinition = {
      ...definition,
      createdAt: definition.createdAt || new Date(),
      updatedAt: new Date(),
    };

    this.components.set(definition.id, enhancedDefinition);

    // 이벤트 발생
    this.emitEvent({
      type: "component_registered",
      data: enhancedDefinition,
      timestamp: new Date(),
    });

    // 개발자 도구 등록 (개발 모드에서만)
    if (process.env.NODE_ENV === "development") {
      this.registerGlobalDevTools();
    }
  }

  /**
   * 컴포넌트 등록 해제
   */
  static unregisterComponent(id: string): void {
    const definition = this.components.get(id);
    if (!definition) {
      return;
    }

    this.components.delete(id);

    // 이벤트 발생
    this.emitEvent({
      type: "component_unregistered",
      data: definition,
      timestamp: new Date(),
    });
  }

  /**
   * 특정 컴포넌트 조회
   */
  static getComponent(id: string): ComponentDefinition | undefined {
    return this.components.get(id);
  }

  /**
   * 모든 컴포넌트 조회
   */
  static getAllComponents(): ComponentDefinition[] {
    return Array.from(this.components.values()).sort((a, b) => {
      // 카테고리별 정렬, 그 다음 이름순
      if (a.category !== b.category) {
        return a.category.localeCompare(b.category);
      }
      return a.name.localeCompare(b.name);
    });
  }

  /**
   * 카테고리별 컴포넌트 조회
   */
  static getByCategory(category: ComponentCategory): ComponentDefinition[] {
    return this.getAllComponents().filter((comp) => comp.category === category);
  }

  /**
   * 웹타입별 컴포넌트 조회
   */
  static getByWebType(webType: WebType): ComponentDefinition[] {
    return this.getAllComponents().filter((comp) => comp.webType === webType);
  }

  /**
   * 컴포넌트 검색
   */
  static search(options: ComponentSearchOptions = {}): ComponentDefinition[] {
    let results = this.getAllComponents();

    // 검색어 필터
    if (options.query) {
      const lowercaseQuery = options.query.toLowerCase();
      results = results.filter(
        (comp) =>
          comp.name.toLowerCase().includes(lowercaseQuery) ||
          comp.nameEng?.toLowerCase().includes(lowercaseQuery) ||
          comp.description.toLowerCase().includes(lowercaseQuery) ||
          comp.tags?.some((tag) => tag.toLowerCase().includes(lowercaseQuery)) ||
          comp.id.toLowerCase().includes(lowercaseQuery),
      );
    }

    // 카테고리 필터
    if (options.category) {
      results = results.filter((comp) => comp.category === options.category);
    }

    // 웹타입 필터
    if (options.webType) {
      results = results.filter((comp) => comp.webType === options.webType);
    }

    // 태그 필터
    if (options.tags && options.tags.length > 0) {
      results = results.filter((comp) => comp.tags?.some((tag) => options.tags!.includes(tag)));
    }

    // 작성자 필터
    if (options.author) {
      results = results.filter((comp) => comp.author === options.author);
    }

    // 페이징
    if (options.offset !== undefined || options.limit !== undefined) {
      const start = options.offset || 0;
      const end = options.limit ? start + options.limit : undefined;
      results = results.slice(start, end);
    }

    return results;
  }

  /**
   * 컴포넌트 존재 여부 확인
   */
  static hasComponent(id: string): boolean {
    return this.components.has(id);
  }

  /**
   * 컴포넌트 수 조회
   */
  static getComponentCount(): number {
    return this.components.size;
  }

  /**
   * 통계 정보 조회
   */
  static getStats(): ComponentStats {
    const components = this.getAllComponents();

    // 카테고리별 통계
    const categoryMap = new Map<ComponentCategory, number>();
    const webTypeMap = new Map<WebType, number>();
    const authorMap = new Map<string, number>();

    components.forEach((comp) => {
      // 카테고리별 집계
      categoryMap.set(comp.category, (categoryMap.get(comp.category) || 0) + 1);

      // 웹타입별 집계
      webTypeMap.set(comp.webType, (webTypeMap.get(comp.webType) || 0) + 1);

      // 작성자별 집계
      if (comp.author) {
        authorMap.set(comp.author, (authorMap.get(comp.author) || 0) + 1);
      }
    });

    // 최근 추가된 컴포넌트 (7개)
    const recentlyAdded = components
      .filter((comp) => comp.createdAt)
      .sort((a, b) => b.createdAt!.getTime() - a.createdAt!.getTime())
      .slice(0, 7);

    return {
      total: components.length,
      byCategory: Array.from(categoryMap.entries()).map(([category, count]) => ({
        category,
        count,
      })),
      byWebType: Array.from(webTypeMap.entries()).map(([webType, count]) => ({
        webType,
        count,
      })),
      byAuthor: Array.from(authorMap.entries()).map(([author, count]) => ({
        author,
        count,
      })),
      recentlyAdded,
    };
  }

  /**
   * 컴포넌트 정의 유효성 검사
   */
  private static validateComponentDefinition(definition: ComponentDefinition): {
    isValid: boolean;
    errors: string[];
    warnings: string[];
  } {
    const errors: string[] = [];
    const warnings: string[] = [];

    // 필수 필드 검사
    if (!definition.id) errors.push("id는 필수입니다");
    if (!definition.name) errors.push("name은 필수입니다");
    if (!definition.description) errors.push("description은 필수입니다");
    if (!definition.category) errors.push("category는 필수입니다");
    if (!definition.webType) errors.push("webType은 필수입니다");
    if (!definition.component) errors.push("component는 필수입니다");
    if (!definition.defaultSize) errors.push("defaultSize는 필수입니다");

    // ID 형식 검사 (kebab-case)
    if (definition.id && !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(definition.id)) {
      errors.push("id는 kebab-case 형식이어야 합니다 (예: button-primary)");
    }

    // 카테고리 유효성 검사
    if (definition.category && !Object.values(ComponentCategory).includes(definition.category)) {
      errors.push(`유효하지 않은 카테고리: ${definition.category}`);
    }

    // 크기 유효성 검사
    if (definition.defaultSize) {
      if (definition.defaultSize.width <= 0) {
        errors.push("defaultSize.width는 0보다 커야 합니다");
      }
      if (definition.defaultSize.height <= 0) {
        errors.push("defaultSize.height는 0보다 커야 합니다");
      }
    }

    // 경고: 권장사항 검사
    if (!definition.icon) warnings.push("아이콘이 설정되지 않았습니다");
    if (!definition.tags || definition.tags.length === 0) {
      warnings.push("검색을 위한 태그가 설정되지 않았습니다");
    }
    if (!definition.author) warnings.push("작성자가 설정되지 않았습니다");

    return {
      isValid: errors.length === 0,
      errors,
      warnings,
    };
  }

  /**
   * 이벤트 리스너 등록
   */
  static addEventListener(listener: (event: ComponentRegistryEvent) => void): void {
    this.eventListeners.push(listener);
  }

  /**
   * 이벤트 리스너 제거
   */
  static removeEventListener(listener: (event: ComponentRegistryEvent) => void): void {
    const index = this.eventListeners.indexOf(listener);
    if (index !== -1) {
      this.eventListeners.splice(index, 1);
    }
  }

  /**
   * 이벤트 발생
   */
  private static emitEvent(event: ComponentRegistryEvent): void {
    this.eventListeners.forEach((listener) => {
      try {
        listener(event);
      } catch (error) {
        console.error("컴포넌트 레지스트리 이벤트 리스너 오류:", error);
      }
    });
  }

  /**
   * 레지스트리 초기화 (테스트용)
   */
  static clear(): void {
    this.components.clear();
    this.eventListeners.length = 0;
  }

  /**
   * 브라우저 개발자 도구 등록
   */
  private static registerGlobalDevTools(): void {
    if (typeof window !== "undefined") {
      (window as any).__COMPONENT_REGISTRY__ = {
        // 기본 조회 기능
        list: () => this.getAllComponents(),
        get: (id: string) => this.getComponent(id),
        has: (id: string) => this.hasComponent(id),
        count: () => this.getComponentCount(),

        // 검색 및 필터링
        search: (query: string) => this.search({ query }),
        byCategory: (category: ComponentCategory) => this.getByCategory(category),
        byWebType: (webType: WebType) => this.getByWebType(webType),

        // 통계 및 분석
        stats: () => this.getStats(),
        categories: () => Object.values(ComponentCategory),
        webTypes: () => Object.values(WebType),

        // 개발자 유틸리티
        validate: (definition: ComponentDefinition) => this.validateComponentDefinition(definition),
        clear: () => this.clear(),

        // Hot Reload 제어
        hotReload: {
          status: async () => {
            // hotReload 기능 제거 (불필요)
            return {
              active: false,
              componentCount: this.getComponentCount(),
              timestamp: new Date(),
            };
          },
          force: async () => {
            // hotReload 기능 비활성화 (불필요)
          },
        },

        // 도움말
        help: () => {
          console.log(`
🎨 컴포넌트 레지스트리 개발자 도구

기본 명령어:
  __COMPONENT_REGISTRY__.list()              - 모든 컴포넌트 목록
  __COMPONENT_REGISTRY__.get("button-primary") - 특정 컴포넌트 조회
  __COMPONENT_REGISTRY__.count()             - 등록된 컴포넌트 수

검색 및 필터링:
  __COMPONENT_REGISTRY__.search("버튼")      - 컴포넌트 검색
  __COMPONENT_REGISTRY__.byCategory("input") - 카테고리별 조회
  __COMPONENT_REGISTRY__.byWebType("button") - 웹타입별 조회

통계 및 분석:
  __COMPONENT_REGISTRY__.stats()             - 통계 정보
  __COMPONENT_REGISTRY__.categories()        - 사용 가능한 카테고리
  __COMPONENT_REGISTRY__.webTypes()          - 사용 가능한 웹타입

Hot Reload 제어 (비동기):
  await __COMPONENT_REGISTRY__.hotReload.status()  - Hot Reload 상태 확인
  await __COMPONENT_REGISTRY__.hotReload.force()   - 강제 컴포넌트 재로드

개발자 도구:
  __COMPONENT_REGISTRY__.validate(def)       - 컴포넌트 정의 검증
  __COMPONENT_REGISTRY__.clear()             - 레지스트리 초기화
  __COMPONENT_REGISTRY__.debug()             - 디버그 정보 출력
  __COMPONENT_REGISTRY__.export()            - JSON으로 내보내기
  __COMPONENT_REGISTRY__.help()              - 이 도움말

💡 사용 예시:
  __COMPONENT_REGISTRY__.search("input")
  __COMPONENT_REGISTRY__.byCategory("input")
  __COMPONENT_REGISTRY__.get("text-input")
          `);
        },
      };
    }
  }

  /**
   * 디버그 정보 출력
   */
  static debug(): void {
    // 디버그 로그 제거 (필요시 브라우저 콘솔에서 ComponentRegistry.getStats() 사용)
  }

  /**
   * JSON으로 내보내기
   */
  static export(): string {
    const data = {
      timestamp: new Date().toISOString(),
      version: "1.0.0",
      components: Array.from(this.components.entries()).map(([id, definition]) => ({
        id,
        definition: {
          ...definition,
          // React 컴포넌트는 직렬화할 수 없으므로 제외
          component: definition.component.name,
          renderer: definition.renderer?.name,
          configPanel: definition.configPanel?.name,
        },
      })),
    };

    return JSON.stringify(data, null, 2);
  }
}
