/**
 * Tesseract.js OCR Provider
 * 特点：免费、本地运行、支持多语言
 * 缺点：速度较慢、准确率中等
 */

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

interface TesseractModule {
  recognize: (
    image: string | Buffer,
    lang: string,
    options?: { logger?: (m: any) => void }
  ) => Promise<{ data: { text: string; confidence: number } }>;
}

export class TesseractProvider extends BaseOCRProvider {
  private tesseract: TesseractModule | null = null;
  private initialized = false;

  constructor(config: OCRProviderConfig = {}) {
    super(config);
  }

  getName(): string {
    return 'Tesseract.js';
  }

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

  /**
   * 检查 Tesseract.js 是否已安装
   */
  async isAvailable(): Promise<boolean> {
    if (this.initialized) {
      return this.tesseract !== null;
    }

    try {
      const module = await import('tesseract.js');
      // tesseract.js 是默认导出，需要使用 .default
      this.tesseract = (module as any).default || module;
      this.initialized = true;
      return true;
    } catch {
      this.initialized = true;
      return false;
    }
  }

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

    // 确定语言
    const language = options?.language || this.config.language || 'chi_sim+eng';

    // 获取图片数据
    const imageData = await this.getImageData(source);

    // 动态导入 tesseract.js
    try {
      const tesseractModule = await import('tesseract.js');
      const Tesseract = (tesseractModule as any).default || tesseractModule;

      const result = await this.withTimeout(
        Tesseract.recognize(imageData, language, {
          logger: (m: any) => {
            if (m.status === 'recognizing text') {
              // 可选：记录进度
              // console.log(`Tesseract progress: ${(m.progress * 100).toFixed(0)}%`);
            }
          },
        }),
        options?.timeout || this.config.timeout || 30000
      ) as { data: { text: string; confidence: number } };

      const duration = Date.now() - startTime;

      return {
        text: this.cleanText(result.data.text),
        confidence: result.data.confidence / 100, // Tesseract 返回 0-100
        duration,
        extra: {
          provider: 'tesseract.js',
          language,
        },
      };
    } catch (error) {
      if (error instanceof Error && error.message === 'timeout') {
        throw new Error('OCR 识别超时');
      }
      throw error;
    }
  }

  getRecommendations() {
    return {
      ...super.getRecommendations(),
      notes: '首次运行会下载语言包 (约 20MB)，后续运行会更快。适合少量图片处理。',
    };
  }

  /**
   * 获取图片数据 (路径或 Buffer)
   */
  private async getImageData(source: IImageSource): Promise<string | Buffer> {
    if (source.buffer) {
      return source.buffer;
    }

    if (source.path) {
      // 使用基类的路径解析方法
      const fullPath = this.resolveImagePath(source.path);

      if (!fs.existsSync(fullPath)) {
        throw new Error(`图片文件不存在: ${fullPath}`);
      }

      return fullPath;
    }

    if (source.base64) {
      // Tesseract.js 支持 Base64，需要添加 data URL 前缀
      const base64Data = source.base64.startsWith('data:')
        ? source.base64
        : `data:image/png;base64,${source.base64}`;
      return base64Data;
    }

    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)
      ),
    ]);
  }

  /**
   * 清理识别结果文本
   */
  private cleanText(text: string): string {
    return text
      .replace(/\s+/g, ' ') // 多个空格合并为一个
      .replace(/\n\s*\n/g, '\n\n') // 多个空行合并
      .trim();
  }
}

// 导出单例实例
export const tesseractProvider = new TesseractProvider();
