import { Card } from '../../types';
import { cardModelService } from '../../services/CardModelService';
import { CentroidTracker } from '../../utils/Tracker';
import { ImageProcessing } from '../../utils/ImageProcessing';
import { ImageGeometry } from '../../utils/image-geometry';
import { getMostCommon, detectCardSuit, detectCardValue } from './DetectionUtils';

export class DetectionPipeline {
  private tracker = new CentroidTracker();
  private classificationHistory = new Map<number, { suits: string[], values: number[] }>();

  async processImageForCards(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D): Promise<Card[]> {
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    
    const edges = ImageProcessing.detectEdges(imageData);
    const cardPolygons = ImageGeometry.findRectangularRegions(edges, canvas.width, canvas.height);
    
    const detectedCards: Card[] = [];

    for (let i = 0; i < cardPolygons.length; i++) {
      const polygon = cardPolygons[i];
      
       const corners = ImageGeometry.findCorners(polygon.points);
       const cardCrop = ImageGeometry.warpPerspective(canvas, corners, 128, 192);
      
      let suit: 'Schellen' | 'Schilten' | 'Eicheln' | 'Rosen';
      let value: number;
      let confidence = 0.85;

      if (cardModelService.isReady()) {
        const suitRes = await cardModelService.classifySuit(cardCrop);
        const valRes = await cardModelService.classifyValue(cardCrop);
        
        // Only proceed if confidence is above a certain threshold
        const MIN_CONFIDENCE = 0.6;
        if (suitRes.confidence < MIN_CONFIDENCE || valRes.confidence < MIN_CONFIDENCE) {
          continue;
        }

        suit = suitRes.label as any;
        value = parseInt(valRes.label);
        confidence = (suitRes.confidence + valRes.confidence) / 2;
      } else {
        suit = detectCardSuit(ctx, canvas, polygon.bbox);
        value = detectCardValue(ctx, canvas, polygon.bbox);
      }
      
      detectedCards.push({
        id: `card-${i}`,
        suit,
        value,
        x: polygon.bbox.x,
        y: polygon.bbox.y,
        width: polygon.bbox.width,
        height: polygon.bbox.height,
        confidence
      });
    }
    
    const trackedObjects = this.tracker.update(cardPolygons.map(p => p.bbox));
    const finalCards: Card[] = [];

    for (const obj of trackedObjects) {
      const detection = detectedCards.find(c => 
        Math.abs(c.x - obj.bbox.x) < 20 && Math.abs(c.y - obj.bbox.y) < 20
      );

      if (detection) {
        if (!this.classificationHistory.has(obj.id)) {
          this.classificationHistory.set(obj.id, { suits: [], values: [] });
        }
        const history = this.classificationHistory.get(obj.id)!;
        history.suits.push(detection.suit);
        history.values.push(detection.value);
        if (history.suits.length > 10) {
          history.suits.shift();
          history.values.shift();
        }

        const bestSuit = getMostCommon(history.suits) as any;
        const bestValue = Number(getMostCommon(history.values));

        finalCards.push({
          id: `card-${obj.id}`,
          suit: bestSuit,
          value: bestValue,
          x: obj.bbox.x,
          y: obj.bbox.y,
          width: obj.bbox.width,
          height: obj.bbox.height,
          confidence: detection.confidence
        });
      }
    }
    
    return finalCards;
  }
}
