/**
 * Component Registry System
 * 서비스 티어별 컴포넌트 관리 시스템
 */

import {
  ComponentRegistry,
  ComponentDefinition,
  ComponentType,
  ServiceTier,
  BaseComponent,
  ComponentSettings,
  ComponentSchema,
} from "../../types/template-system";

export class TemplateComponentRegistry implements ComponentRegistry {
  private components: Map<string, ComponentDefinition> = new Map();
  private tierComponents: Map<ServiceTier, Set<ComponentType>> = new Map();

  constructor() {
    this.initializeTierMappings();
  }

  /**
   * 서비스 티어별 사용 가능한 컴포넌트 초기화
   */
  private initializeTierMappings(): void {
    // Starter 티어 - 기본 컴포넌트만
    this.tierComponents.set(
      ServiceTier.STARTER,
      new Set([
        ComponentType.HERO,
        ComponentType.ABOUT,
        ComponentType.CONTACT,
        ComponentType.FOOTER,
      ])
    );

    // Standard 티어 - Starter + 추가 컴포넌트
    this.tierComponents.set(
      ServiceTier.STANDARD,
      new Set([
        ComponentType.HERO,
        ComponentType.ABOUT,
        ComponentType.SERVICES,
        ComponentType.TESTIMONIALS,
        ComponentType.BLOG,
        ComponentType.CONTACT,
        ComponentType.FOOTER,
      ])
    );

    // Plus 티어 - 모든 컴포넌트
    this.tierComponents.set(
      ServiceTier.PLUS,
      new Set([
        ComponentType.HERO,
        ComponentType.ABOUT,
        ComponentType.SERVICES,
        ComponentType.TESTIMONIALS,
        ComponentType.BLOG,
        ComponentType.CONTACT,
        ComponentType.FOOTER,
        ComponentType.TEAM,
        ComponentType.GALLERY,
        ComponentType.NEWSLETTER,
        ComponentType.CASE_STUDIES,
      ])
    );
  }

  /**
   * 컴포넌트 등록
   */
  register(component: ComponentDefinition): void {
    const key = this.getComponentKey(component.type, component.tier);
    this.components.set(key, component);
  }

  /**
   * 특정 티어의 컴포넌트 조회
   */
  get(type: ComponentType, tier: ServiceTier): ComponentDefinition | null {
    // 요청된 티어에서 컴포넌트가 사용 가능한지 확인
    if (!this.isComponentAvailableInTier(type, tier)) {
      return null;
    }

    // 정확한 티어의 컴포넌트를 먼저 찾기
    let key = this.getComponentKey(type, tier);
    let component = this.components.get(key);

    if (component) {
      return component;
    }

    // 하위 호환성을 위해 낮은 티어의 컴포넌트 찾기
    const tierHierarchy = [
      ServiceTier.STARTER,
      ServiceTier.STANDARD,
      ServiceTier.PLUS,
    ];
    const currentTierIndex = tierHierarchy.indexOf(tier);

    for (let i = currentTierIndex - 1; i >= 0; i--) {
      key = this.getComponentKey(type, tierHierarchy[i]);
      component = this.components.get(key);
      if (component) {
        return component;
      }
    }

    return null;
  }

  /**
   * 특정 티어에서 사용 가능한 모든 컴포넌트 조회
   */
  getAvailable(tier: ServiceTier): ComponentDefinition[] {
    const availableTypes = this.tierComponents.get(tier) || new Set();
    const components: ComponentDefinition[] = [];

    availableTypes.forEach((type) => {
      const component = this.get(type, tier);
      if (component) {
        components.push(component);
      }
    });

    return components.sort((a, b) => a.name.localeCompare(b.name));
  }

  /**
   * 컴포넌트가 특정 티어에서 유효한지 검증
   */
  validate(component: BaseComponent, tier: ServiceTier): boolean {
    // 컴포넌트가 해당 티어에서 사용 가능한지 확인
    if (!this.isComponentAvailableInTier(component.type, tier)) {
      return false;
    }

    // 컴포넌트가 등록되어 있는지 확인
    const definition = this.get(component.type, tier);
    if (!definition) {
      return false;
    }

    // 컴포넌트 설정이 스키마에 맞는지 검증
    return this.validateComponentSettings(
      component.settings,
      definition.schema
    );
  }

  /**
   * 컴포넌트가 특정 티어에서 사용 가능한지 확인
   */
  private isComponentAvailableInTier(
    type: ComponentType,
    tier: ServiceTier
  ): boolean {
    const availableComponents = this.tierComponents.get(tier);
    return availableComponents ? availableComponents.has(type) : false;
  }

  /**
   * 컴포넌트 키 생성
   */
  private getComponentKey(type: ComponentType, tier: ServiceTier): string {
    return `${type}-${tier}`;
  }

  /**
   * 컴포넌트 설정이 스키마에 맞는지 검증
   */
  private validateComponentSettings(
    settings: ComponentSettings,
    _schema: ComponentSchema
  ): boolean {
    // 기본 필수 필드 확인
    if (
      typeof settings.enabled !== "boolean" ||
      typeof settings.visible !== "boolean" ||
      typeof settings.customizable !== "boolean"
    ) {
      return false;
    }

    // 추가 스키마 검증 로직은 필요에 따라 구현
    return true;
  }

  /**
   * 등록된 모든 컴포넌트 조회
   */
  getAllComponents(): ComponentDefinition[] {
    return Array.from(this.components.values());
  }

  /**
   * 특정 타입의 모든 티어 버전 조회
   */
  getComponentVariants(type: ComponentType): ComponentDefinition[] {
    const variants: ComponentDefinition[] = [];

    [ServiceTier.STARTER, ServiceTier.STANDARD, ServiceTier.PLUS].forEach(
      (tier) => {
        const component = this.get(type, tier);
        if (component) {
          variants.push(component);
        }
      }
    );

    return variants;
  }

  /**
   * 컴포넌트 등록 해제
   */
  unregister(type: ComponentType, tier: ServiceTier): boolean {
    const key = this.getComponentKey(type, tier);
    return this.components.delete(key);
  }

  /**
   * 레지스트리 초기화
   */
  clear(): void {
    this.components.clear();
  }

  /**
   * 티어 업그레이드 시 사용 가능한 새로운 컴포넌트 조회
   */
  getNewComponentsForTierUpgrade(
    fromTier: ServiceTier,
    toTier: ServiceTier
  ): ComponentType[] {
    const fromComponents = this.tierComponents.get(fromTier) || new Set();
    const toComponents = this.tierComponents.get(toTier) || new Set();

    const newComponents: ComponentType[] = [];
    toComponents.forEach((component) => {
      if (!fromComponents.has(component)) {
        newComponents.push(component);
      }
    });

    return newComponents;
  }

  /**
   * 티어별 컴포넌트 제한 확인
   */
  getTierRestrictions(tier: ServiceTier): {
    allowedComponents: ComponentType[];
    restrictedComponents: ComponentType[];
  } {
    const allowedComponents = Array.from(this.tierComponents.get(tier) || []);
    const allComponents = Object.values(ComponentType);
    const restrictedComponents = allComponents.filter(
      (comp) => !allowedComponents.includes(comp)
    );

    return {
      allowedComponents,
      restrictedComponents,
    };
  }
}

// 싱글톤 인스턴스 export
export const componentRegistry = new TemplateComponentRegistry();
