/**
 * PaddleOCR Provider
 * 特点：高精度、多语言支持、本地运行
 * 基于 PaddlePaddle 深度学习框架
 *
 * 部署方式：
 * 1. 使用 Docker: docker run -p 8866:8866 987846/paddleocr:latest
 *
 * GitHub: https://github.com/PaddlePaddle/PaddleOCR
 * Docker Hub: https://hub.docker.com/r/paddlepaddle/paddleocr
 */

import { BaseOCRProvider, IImageSource, OCRRecognitionResult, OCRProviderConfig } from './base.provider';
import fs from 'fs';

interface PaddleOCRResponse {
  msg: string;
  results: Array<Array<{
    boxes: number[][];
    rec_text: string;
    rec_score: number;
  }>>;
  status: string;
}

interface PaddleOCRRequest {
  images: string[];
}

export class PaddleOCRProvider extends BaseOCRProvider {
  private apiUrl: string;

  constructor(config: OCRProviderConfig & { apiUrl?: string } = {}) {
    super(config);
    this.apiUrl = config.apiUrl || process.env.PADDLEOCR_API_URL || 'http://localhost:13059';
  }

  getName(): string {
    return 'PaddleOCR';
  }

  getType(): 'local' | 'cloud' {
    return 'local';
  }

  /**
   * 检查 PaddleOCR 服务是否可用
   */
  async isAvailable(): Promise<boolean> {
    try {
      const response = await fetch(`${this.apiUrl}/`, { signal: AbortSignal.timeout(3000) });
      // PaddleOCR 服务正常时返回 200
      return response.ok || response.status === 200;
    } catch {
      // 服务不可用
      return false;
    }
  }

  /**
   * 执行 OCR 识别
   */
  async recognize(
    source: IImageSource,
    options?: OCRProviderConfig
  ): Promise<OCRRecognitionResult> {
    const startTime = Date.now();

    // 获取图片 Base64
    const imageBase64 = await this.getImageBase64(source);

    // 调用 PaddleOCR API
    const response = await this.withTimeout(
      fetch(`${this.apiUrl}/predict/ocr_system`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          images: [imageBase64],
        } as PaddleOCRRequest),
      }),
      options?.timeout || this.config.timeout || 30000
    );

    const data = (await response.json()) as PaddleOCRResponse;
    const duration = Date.now() - startTime;

    // 检查错误
    if (data.status !== '000' && data.status !== '200') {
      throw new Error(`PaddleOCR 错误: ${data.msg || data.status}`);
    }

    // 提取文本和置信度
    const ocrResults = data.results[0] || [];
    const text = ocrResults.map((r) => r.rec_text).join('\n');

    // 计算平均置信度
    const confidence = ocrResults.length > 0
      ? ocrResults.reduce((acc, r) => acc + (r.rec_score || 0), 0) / ocrResults.length
      : 0;

    return {
      text: text.trim(),
      confidence,
      duration,
      extra: {
        provider: 'paddleocr',
        textCount: ocrResults.length,
      },
    };
  }

  getRecommendations() {
    return {
      maxImageSize: 10 * 1024 * 1024,
      supportedFormats: ['jpg', 'jpeg', 'png', 'webp', 'bmp'],
      notes: 'PaddleOCR 是百度开源的 OCR 工具，支持多语言识别，准确率高。需要先启动 PaddleOCR 服务。',
    };
  }

  /**
   * 获取图片 Base64
   */
  private async getImageBase64(source: IImageSource): Promise<string> {
    if (source.base64) {
      // 移除 data URL 前缀
      return source.base64.replace(/^data:image\/\w+;base64,/, '');
    }

    if (source.buffer) {
      return source.buffer.toString('base64');
    }

    if (source.path) {
      // 使用基类的路径解析方法
      const fullPath = this.resolveImagePath(source.path);
      const buffer = fs.readFileSync(fullPath);
      return buffer.toString('base64');
    }

    throw new Error('无效的图片来源');
  }

  /**
   * 超时包装
   */
  private async withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {
    return Promise.race([
      promise,
      new Promise<never>((_, reject) =>
        setTimeout(() => reject(new Error('timeout')), timeout)
      ),
    ]);
  }
}

// 导出单例实例
export const paddleocrProvider = new PaddleOCRProvider();
