/**
 * @file 人脸检测结果转换器
 * @description 将 face-api 检测结果转换为标准格式
 * @module modules/face/face-result-converter
 */

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

/**
 * 人脸关键点索引（对应 face-api 的 68 点模型）
 */
export const FaceLandmarkIndex = {
  LEFT_EYE: 36,
  RIGHT_EYE: 45,
  NOSE: 30,
  MOUTH_CENTER: 57
} as const;

/**
 * face-api 原始检测结果
 */
export interface RawFaceDetection {
  /** 检测框 */
  detection?: {
    box?: { x?: number; y?: number; width?: number; height?: number };
    score?: number;
  };
  /** 关键点 */
  landmarks?: {
    positions: Array<{ x: number; y: number }>;
  };
  /** 表情 */
  expressions?: {
    angry?: number;
    disgusted?: number;
    fearful?: number;
    happy?: number;
    neutral?: number;
    sad?: number;
    surprised?: number;
  };
  /** 年龄 */
  age?: number;
  /** 性别 */
  gender?: string;
  /** 性别概率 */
  genderProbability?: number;
  /** 人脸描述符（特征向量） */
  descriptor?: Float32Array | number[];
}

/**
 * 结果转换器配置
 */
export interface ResultConverterConfig {
  /** 是否检测关键点 */
  detectLandmarks: boolean;
  /** 关键点模型类型 */
  landmarksModel: 'tiny' | '68_points';
  /** 是否检测表情 */
  detectExpressions: boolean;
  /** 是否检测年龄和性别 */
  detectAgeGender: boolean;
  /** 是否提取特征向量 */
  extractEmbeddings: boolean;
}

/**
 * 人脸检测结果转换器
 *
 * 负责将 face-api 原始检测结果转换为标准格式
 */
export class FaceResultConverter {
  /** 配置 */
  private config: ResultConverterConfig;

  /**
   * 构造函数
   * @param config 转换器配置
   */
  constructor(config: ResultConverterConfig) {
    this.config = config;
  }

  /**
   * 批量转换检测结果
   * @param detections 原始检测结果数组
   * @param options 检测选项
   * @param processingTime 处理时间
   * @returns 标准化检测结果
   */
  convertBatch(
    detections: RawFaceDetection[],
    options: {
      maxFaces?: number;
      enableTracking?: boolean;
    },
    processingTime: number
  ): FaceDetectionResult[] {
    // 限制检测数量
    const maxFaces = options.maxFaces || 10;
    const limitedDetections = detections.slice(0, maxFaces);

    const results: FaceDetectionResult[] = [];

    for (const detection of limitedDetections) {
      const result = this.convertSingle(detection, processingTime);
      results.push(result);
    }

    return results;
  }

  /**
   * 转换单个检测结果
   * @param detection 原始检测结果
   * @param processingTime 处理时间
   * @returns 标准化检测结果
   */
  convertSingle(detection: RawFaceDetection, processingTime: number): FaceDetectionResult {
    // 转换边界框
    const boundingBox: Rect = {
      x: detection.detection?.box?.x || 0,
      y: detection.detection?.box?.y || 0,
      width: detection.detection?.box?.width || 0,
      height: detection.detection?.box?.height || 0
    };

    // 创建基本结果
    const result: FaceDetectionResult = {
      id: generateUUID(),
      type: 'face',
      boundingBox,
      confidence: detection.detection?.score || 0,
      processingTime,
      timestamp: Date.now()
    };

    // 转换关键点
    if (detection.landmarks && this.config.detectLandmarks) {
      result.landmarks = this.convertLandmarks(detection.landmarks);
    }

    // 转换表情属性
    if (detection.expressions && this.config.detectExpressions) {
      result.attributes = {
        ...result.attributes,
        emotion: {
          angry: detection.expressions.angry || 0,
          disgust: detection.expressions.disgusted || 0,
          fear: detection.expressions.fearful || 0,
          happy: detection.expressions.happy || 0,
          neutral: detection.expressions.neutral || 0,
          sad: detection.expressions.sad || 0,
          surprise: detection.expressions.surprised || 0
        }
      };
    }

    // 转换年龄
    if (detection.age !== undefined && this.config.detectAgeGender) {
      result.attributes = {
        ...result.attributes,
        age: detection.age
      };
    }

    // 转换性别
    if (detection.gender !== undefined && detection.genderProbability !== undefined && this.config.detectAgeGender) {
      result.attributes = {
        ...result.attributes,
        gender: detection.gender === 'male' ? detection.genderProbability : 1 - detection.genderProbability
      };
    }

    // 转换特征向量
    if (detection.descriptor && this.config.extractEmbeddings) {
      result.embedding = {
        vector: Array.from(detection.descriptor),
        dimension: detection.descriptor.length
      };
    }

    return result;
  }

  /**
   * 转换关键点
   */
  private convertLandmarks(landmarks: RawFaceDetection['landmarks']): FaceDetectionResult['landmarks'] {
    if (!landmarks || !landmarks.positions) {
      return undefined as any;
    }

    const positions = landmarks.positions;

    return {
      leftEye: {
        x: positions[FaceLandmarkIndex.LEFT_EYE].x,
        y: positions[FaceLandmarkIndex.LEFT_EYE].y
      },
      rightEye: {
        x: positions[FaceLandmarkIndex.RIGHT_EYE].x,
        y: positions[FaceLandmarkIndex.RIGHT_EYE].y
      },
      nose: {
        x: positions[FaceLandmarkIndex.NOSE].x,
        y: positions[FaceLandmarkIndex.NOSE].y
      },
      mouth: {
        x: positions[FaceLandmarkIndex.MOUTH_CENTER].x,
        y: positions[FaceLandmarkIndex.MOUTH_CENTER].y
      },
      points: positions.map((p) => ({ x: p.x, y: p.y }))
    };
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<ResultConverterConfig>): void {
    this.config = { ...this.config, ...config };
  }
}
