/**
 * @file 人脸跟踪器
 * @description 提供人脸跟踪功能，基于 IOU 匹配算法
 * @module modules/face/face-tracker
 */

import { FaceDetectionResult, Rect } from '../../interfaces/face-detection';
import { generateUUID } from '../../utils';

/**
 * 人脸跟踪状态
 */
interface FaceTrackerState {
  /** 跟踪ID */
  trackId: string;
  /** 最后检测到的时间戳 */
  lastSeen: number;
  /** 检测结果 */
  detection: FaceDetectionResult;
  /** 连续跟踪帧数 */
  consecutiveFrames: number;
}

/**
 * 人脸跟踪器配置
 */
export interface FaceTrackerConfig {
  /** 跟踪超时时间(ms)，超过此时间未检测到则移除 */
  trackTimeout?: number;
  /** 匹配阈值，值越小越严格 */
  matchThreshold?: number;
}

/**
 * 人脸跟踪器
 *
 * 基于 IOU（交并比）和中心点距离的人脸跟踪算法
 */
export class FaceTracker {
  /** 跟踪状态映射 */
  private trackers: Map<string, FaceTrackerState> = new Map();

  /** 配置 */
  private config: Required<FaceTrackerConfig>;

  /**
   * 构造函数
   * @param config 跟踪器配置
   */
  constructor(config: FaceTrackerConfig = {}) {
    this.config = {
      trackTimeout: config.trackTimeout ?? 1000,
      matchThreshold: config.matchThreshold ?? 0.3
    };
  }

  /**
   * 计算两个矩形的 IOU（交并比）
   */
  private computeIOU(a: Rect, b: Rect): number {
    const x1 = Math.max(a.x, b.x);
    const y1 = Math.max(a.y, b.y);
    const x2 = Math.min(a.x + a.width, b.x + b.width);
    const y2 = Math.min(a.y + a.height, b.y + b.height);

    if (x2 <= x1 || y2 <= y1) {
      return 0;
    }

    const intersection = (x2 - x1) * (y2 - y1);
    const areaA = a.width * a.height;
    const areaB = b.width * b.height;
    const union = areaA + areaB - intersection;

    return union > 0 ? intersection / union : 0;
  }

  /**
   * 计算两个矩形的中心点距离
   */
  private computeCenterDistance(a: Rect, b: Rect): number {
    const centerA = {
      x: a.x + a.width / 2,
      y: a.y + a.height / 2
    };
    const centerB = {
      x: b.x + b.width / 2,
      y: b.y + b.height / 2
    };

    return Math.sqrt(
      Math.pow(centerA.x - centerB.x, 2) +
      Math.pow(centerA.y - centerB.y, 2)
    );
  }

  /**
   * 匹配检测结果到现有跟踪器
   * @param detections 当前帧的检测结果
   * @returns 更新后的跟踪结果（带有 trackId）
   */
  update(detections: FaceDetectionResult[]): FaceDetectionResult[] {
    const now = Date.now();
    const results: FaceDetectionResult[] = [];

    // 清理过期的跟踪器
    for (const [id, tracker] of this.trackers) {
      if (now - tracker.lastSeen > this.config.trackTimeout) {
        this.trackers.delete(id);
      }
    }

    // 标记所有检测结果为"未匹配"
    const unmatchedDetections = [...detections];

    // 尝试将检测结果匹配到现有跟踪器
    for (const [trackId, tracker] of this.trackers) {
      let bestMatchIdx = -1;
      let bestScore = Infinity;

      for (let i = 0; i < unmatchedDetections.length; i++) {
        const detection = unmatchedDetections[i];
        const iou = this.computeIOU(tracker.detection.boundingBox, detection.boundingBox);
        const centerDist = this.computeCenterDistance(
          tracker.detection.boundingBox,
          detection.boundingBox
        );

        // 计算综合分数：IOU 权重 0.4，中心距离权重 0.6
        const maxDim = Math.max(detection.boundingBox.width, detection.boundingBox.height);
        const score = iou * 0.4 + (1 - centerDist / (maxDim * 2)) * 0.6;

        if (score > 0.5 && score < bestScore) {
          bestScore = score;
          bestMatchIdx = i;
        }
      }

      if (bestMatchIdx !== -1) {
        // 匹配成功，更新跟踪器
        const matched = unmatchedDetections[bestMatchIdx];
        matched.trackId = trackId;
        results.push(matched);

        // 更新跟踪状态
        tracker.lastSeen = now;
        tracker.detection = matched;
        tracker.consecutiveFrames++;

        // 移除已匹配的检测
        unmatchedDetections.splice(bestMatchIdx, 1);
      }
    }

    // 剩余未匹配的检测创建新的跟踪器
    for (const detection of unmatchedDetections) {
      const trackId = generateUUID();
      detection.trackId = trackId;
      results.push(detection);

      this.trackers.set(trackId, {
        trackId,
        lastSeen: now,
        detection,
        consecutiveFrames: 1
      });
    }

    return results;
  }

  /**
   * 获取当前跟踪状态
   */
  getTrackerStates(): Map<string, FaceTrackerState> {
    return this.trackers;
  }

  /**
   * 获取活跃跟踪器数量
   */
  getActiveCount(): number {
    const now = Date.now();
    let count = 0;
    for (const [, tracker] of this.trackers) {
      if (now - tracker.lastSeen <= this.config.trackTimeout) {
        count++;
      }
    }
    return count;
  }

  /**
   * 重置跟踪器
   */
  reset(): void {
    this.trackers.clear();
  }

  /**
   * 移除指定跟踪器
   * @param trackId 跟踪ID
   */
  remove(trackId: string): boolean {
    return this.trackers.delete(trackId);
  }
}
