import sharp from 'sharp';
import axios from 'axios';
import db from '../config/database';
import { logger } from '../utils/logger';

/**
 * @description 跨境风控审计内核 (CORE_DEV_04)
 * 实现高性能图像指纹提取内核 (Perceptual Hashing)
 */
export class ImageFingerprintService {
  /**
   * [CORE_AI_10] 跨平台同款视觉检索 (Visual Matcher)
   * @description 从 URL 下载图片并生成 pHash
   */
  static async generateHashFromUrl(url: string): Promise<string> {
    try {
      const response = await axios.get(url, { responseType: 'arraybuffer' });
      const buffer = Buffer.from(response.data);
      return this.generatePHash(buffer);
    } catch (err: any) {
      logger.error(`[ImageFingerprint] Failed to generate hash from URL: ${err.message}`);
      throw err;
    }
  }

  /**
   * [CORE_AI_10] 跨平台同款视觉检索 (Visual Matcher)
   * @description 在数据库中检索与目标指纹相似的商品
   */
  static async findSimilarProducts(targetHash: string, threshold: number = 10): Promise<any[]> {
    try {
      // 1. 获取所有带有 phash 的商品 (在大规模场景下应使用专门的向量库或 BK-Tree)
      const products = await db('cf_product').whereNotNull('phash').select('*');
      
      // 2. 内存中进行海明距离比较
      const results = products.map(p => ({
        ...p,
        distance: this.compare(targetHash, p.phash)
      }))
      .filter(p => p.distance <= threshold)
      .sort((a, b) => a.distance - b.distance);

      logger.info(`[ImageFingerprint] Found ${results.length} similar products for hash: ${targetHash}`);
      return results;
    } catch (err: any) {
      logger.error(`[ImageFingerprint] Failed to find similar products: ${err.message}`);
      throw err;
    }
  }

  /**
   * @description 基于感知哈希 (pHash) 生成图像指纹
   * @param {Buffer} buffer 图像 Buffer
   * @returns {Promise<string>} 64 位 16 进制指纹
   */
  static async generatePHash(buffer: Buffer): Promise<string> {
    try {
      // 1. 缩放图像至 32x32，并转为灰度图 (sequentialRead 开启以降低内存峰值)
      const { data, info } = await sharp(buffer, { sequentialRead: true })
        .resize(32, 32, { fit: 'fill' })
        .grayscale()
        .raw()
        .toBuffer({ resolveWithObject: true });

      // 2. 计算均值
      let total = 0;
      for (let i = 0; i < data.length; i++) {
        total += data[i];
      }
      const mean = total / data.length;

      // 3. 比较每个像素与均值，生成 64 位哈希 (这里使用简单的 8x8 简化版示例)
      // 实际生产中应使用离散余弦变换 (DCT) 增强鲁棒性
      const hash = [];
      const resizedData = await sharp(data, { raw: { width: 32, height: 32, channels: 1 } })
        .resize(8, 8, { fit: 'fill' })
        .raw()
        .toBuffer();

      let binary = '';
      let resizedTotal = 0;
      for (let i = 0; i < resizedData.length; i++) resizedTotal += resizedData[i];
      const resizedMean = resizedTotal / resizedData.length;

      for (let i = 0; i < resizedData.length; i++) {
        binary += resizedData[i] >= resizedMean ? '1' : '0';
      }

      // 4. 转为 16 进制字符串
      const hex = BigInt('0b' + binary).toString(16).padStart(16, '0');
      logger.info(`[ImageFingerprint] Generated pHash: ${hex}`);
      return hex;
    } catch (err: any) {
      logger.error(`[ImageFingerprint] Failed to generate hash: ${err.message}`);
      throw err;
    }
  }

  /**
   * @description 计算两个指纹的海明距离 (Hamming Distance)
   * @param {string} hash1
   * @param {string} hash2
   * @returns {number} 距离 (越小越相似)
   */
  static compare(hash1: string, hash2: string): number {
    const bin1 = BigInt('0x' + hash1).toString(2).padStart(64, '0');
    const bin2 = BigInt('0x' + hash2).toString(2).padStart(64, '0');

    let distance = 0;
    for (let i = 0; i < 64; i++) {
      if (bin1[i] !== bin2[i]) distance++;
    }
    return distance;
  }
}
