// Smart Component Selector with Priority System
// Priority: Magic UI (40%) > Aceternity (30%) > Charts (20%) > UI (10%)
// Preference: Composite components > Primitives

import { componentRegistry, ComponentMetadata, priorityWeights } from './component-registry';
import { FuzzyMatcher } from './fuzzy-matcher';

export interface ComponentSelectionCriteria {
  useCase: string;
  variant?: string;
  size?: string;
  props?: Record<string, any>;
  isComposite?: boolean;
}

export interface ComponentSelectionResult {
  component: ComponentMetadata;
  confidence: number;
  alternatives: ComponentMetadata[];
}

export class SmartComponentSelector {
  // Select the best component based on criteria
  static select(
    useCase: string
  ): ComponentSelectionResult {
    const criteria: ComponentSelectionCriteria = {
      useCase,
      isComposite: true // Prefer composite components
    };

    const candidates = this.findCandidates(criteria);
    const scoredCandidates = this.scoreCandidates(candidates, criteria);
    
    if (scoredCandidates.length === 0) {
      return {
        component: null as any,
        confidence: 0,
        alternatives: []
      };
    }

    const bestMatch = this.selectBestMatch(scoredCandidates);
    
    return {
      component: bestMatch.component,
      confidence: bestMatch.score / 100,
      alternatives: scoredCandidates
        .slice(1, 4)
        .map(c => c.component)
    };
  }

  // Find candidate components
  private static findCandidates(criteria: ComponentSelectionCriteria): ComponentMetadata[] {
    const candidates: ComponentMetadata[] = [];
    
    for (const [, component] of Object.entries(componentRegistry)) {
      // Check if component matches use case
      if (component.useCases.some(uc => criteria.useCase.includes(uc))) {
        candidates.push(component);
      }
    }
    
    return candidates;
  }

  // Score candidates based on criteria
  private static scoreCandidates(
    candidates: ComponentMetadata[],
    criteria: ComponentSelectionCriteria
  ): Array<{ component: ComponentMetadata; score: number; reason: string }> {
    return candidates.map(component => {
      let score = 0;
      const reasons: string[] = [];

      // Priority score (based on component library)
      const priorityScore = priorityWeights[component.category] * 100;
      score += priorityScore;
      reasons.push(`Priority: ${priorityScore}`);

      // Use case match score
      if (component.useCases.some(uc => criteria.useCase.includes(uc))) {
        score += 50;
        reasons.push('Use case match: +50');
      }

      // Composite component bonus
      if (criteria.isComposite && component.isComposite) {
        score += 25;
        reasons.push('Composite component: +25');
      }

      return {
        component,
        score,
        reason: reasons.join(', ')
      };
    }).sort((a, b) => b.score - a.score);
  }

  // Select the best match from scored candidates
  private static selectBestMatch(
    scoredCandidates: Array<{ component: ComponentMetadata; score: number; reason: string }>
  ): { component: ComponentMetadata; score: number; reason: string } {
    return scoredCandidates[0];
  }

  // Utility methods for component discovery
  static getComponentsByCategory(category: 'aceternity' | 'magicui' | 'shadcn' | 'charts' | 'ui'): ComponentMetadata[] {
    return Object.values(componentRegistry).filter(c => c.category === category);
  }

  static getComponentsByUseCase(useCase: string): ComponentMetadata[] {
    return Object.values(componentRegistry).filter(c => 
      c.useCases.some(uc => uc.includes(useCase))
    );
  }

  static getComponentsByTag(tag: string): ComponentMetadata[] {
    return Object.values(componentRegistry).filter(c => 
      c.tags.includes(tag)
    );
  }

  static getAnimationComponents(): ComponentMetadata[] {
    return Object.values(componentRegistry).filter(c => 
      c.animationLevel === 'high' || c.animationLevel === 'medium'
    );
  }

  static getGradientComponents(): ComponentMetadata[] {
    return Object.values(componentRegistry).filter(c => c.hasGradient);
  }

  // Resolve component name using fuzzy matching
  static resolve(componentName: string) {
    return FuzzyMatcher.findBestMatch(componentName);
  }
} 