/**
 * 原生 OCR 模块桥接（plan.md「3.2 原生模块架构 Config Plugin」+「决策 4」）。
 *
 * 定义 RN ↔ 原生 PP-OCRv5(ONNX Runtime) Module 的桥接契约（见 plan.md 决策 7）。
 * 原生实现通过 Config Plugin 注入（plugins/ppocr/），此处定义 JS 调用接口与降级模拟。
 *
 * 生产环境：NativeModules.PpOcr 提供 recognizeText(bitmap) → string
 * 测试环境：用 SimulatedOcrBridge 返回预设文本
 */

import type { OcrEngine } from '../../domain/pipeline/ocrProcessor';
import { logger } from '../../utils/logger';

/** 原生 OCR 模块契约（由 Config Plugin 注入的原生模块实现）。 */
export interface NativeOcrModule {
  /** 识别图片中的文本（base64 图片输入，返回纯文本）。 */
  recognizeText(imageBase64: string): Promise<string>;
  /** 识别并返回带坐标的文本块（用于复杂版面）。 */
  recognizeTextBlocks(imageBase64: string): Promise<OcrTextBlock[]>;
  /** OCR 引擎是否已就绪（模型加载完成）。 */
  isReady(): Promise<boolean>;
  /** 设置模型文件目录（绝对路径），触发从 filesystem 重新加载模型。 */
  setModelDir(dir: string): Promise<boolean>;
}

export interface OcrTextBlock {
  text: string;
  x: number;
  y: number;
  width: number;
  height: number;
  confidence: number;
}

/**
 * 原生 OCR 桥接：把 NativeOcrModule 适配为 OcrEngine。
 * 若原生模块未加载（Web/测试环境），降级到注入的 fallback。
 */
export class NativeOcrBridge implements OcrEngine {
  constructor(
    private readonly native: NativeOcrModule | null,
    private readonly fallback?: OcrEngine,
  ) {}

  async recognizeText(imageBase64: string): Promise<string> {
    if (this.native) {
      try {
        return await this.native.recognizeText(imageBase64);
      } catch (e) {
        // 原生失败，降级
        if (this.fallback) return this.fallback.recognizeText(imageBase64);
        throw e;
      }
    }
    // 无原生模块
    if (this.fallback) return this.fallback.recognizeText(imageBase64);
    throw new Error('OCR 原生模块未加载，且无降级实现');
  }
}

/**
 * 模拟 OCR 桥接（测试/demo 用）。
 * 按图片内容关键词返回预设文本，便于验证流程。
 */
export class SimulatedOcrBridge implements OcrEngine {
  private presets = new Map<string, string>();

  /** 注入预设：图片标识 → OCR 文本。 */
  preset(imageKey: string, text: string): void {
    this.presets.set(imageKey, text);
  }

  async recognizeText(imageBase64: string): Promise<string> {
    // 简单匹配：遍历预设找 key
    for (const [key, text] of this.presets) {
      if (imageBase64.includes(key)) return text;
    }
    return '';
  }
}

/**
 * 获取原生 OCR 模块（RN 环境用）。
 * 在非 RN 环境（测试）返回 null，调用方应提供 fallback。
 */
export function getNativeOcrModule(): NativeOcrModule | null {
  // RN 环境：从 NativeModules 取 PpOcr（由 Config Plugin 注入）
  try {
    const { NativeModules } = require('react-native');
    return (NativeModules.PpOcr as NativeOcrModule | undefined) ?? null;
  } catch {
    // 非 RN 环境（测试）：react-native 不可用
    return null;
  }
}

/**
 * 获取配置好的 OcrEngine 实例（用于 OcrProcessor）。
 * RN 环境用 NativeOcrBridge 包裹原生模块；无原生模块时抛错。
 *
 * @param modelDir 可选：模型文件目录绝对路径，传入时通知原生模块从该目录加载模型。
 */
/** 上次传给原生模块的模型目录，避免冗余 setModelDir 导致引擎被释放重建。 */
let _lastNativeModelDir: string | undefined;

export function getNativeOcrBridge(modelDir?: string): OcrEngine {
  const native = getNativeOcrModule();
  if (!native) {
    throw new Error('OCR engine not available');
  }
  // P8：设置模型目录（从 filesystem 加载 ONNX，替代 asset 内联）
  // 说明：此处为 fire-and-forget。原生侧 ensureReady() 已用 initLatch 阻塞等待
  // 异步 initEngine 完成（最多 15s），因此后续 recognizeText 会自然等待重载结束，
  // 不会因为 setModelDir 未 await 而读到未就绪状态。这里只暴露错误用于排查。
  if (modelDir && modelDir !== _lastNativeModelDir) {
    _lastNativeModelDir = modelDir;
    native.setModelDir(modelDir).catch(e => {
      logger.error('ocrBridge', `setModelDir 失败（目录: ${modelDir}）`, e);
    });
  }
  return new NativeOcrBridge(native);
}
