/**
 * 截图自动记账通道（plan.md「3.13 截图自动记账通道」）。
 *
 * Android：ContentObserver 监听 MediaStore Screenshots 目录
 * iOS：AppIntent 后台执行（iOS 16+）
 *
 * 原生监听通过 Config Plugin 注入，此处定义事件桥接 + 去重 + 协调 OCR 处理。
 */

import { DEDUP_CACHE_MAX, SCREENSHOT_KEYWORDS, SCREENSHOT_TIME_WINDOW_MS } from '../../domain/core/constants';
import { hash } from '../../domain/core/ledger';
import type { OcrProcessor, OcrProcessResult } from '../../domain/pipeline/ocrProcessor';
import { logger } from '../../utils/logger';

/** 截图事件（原生监听器推送）。 */
export interface ScreenshotEvent {
  /** 图片 URI（content:// 或 file://）。 */
  uri: string;
  /** 图片 base64（若原生已读取）。 */
  base64?: string;
  /** 来源包名（Android 可选）。 */
  packageName?: string;
  /** 截图时间戳。 */
  timestamp: number;
}

/** 原生截图监听器契约（由 Config Plugin 注入）。 */
export interface ScreenshotListener {
  /** 开始监听。 */
  start(handler: (event: ScreenshotEvent) => void): Promise<void>;
  /** 停止监听。 */
  stop(): Promise<void>;
  /** 是否正在监听。 */
  isListening(): boolean;
}

/**
 * 截图通道协调器：去重 + OCR 处理。
 *
 * 去重逻辑参考 BeeCount ScreenshotObserver：
 * - processedPaths 持久化，避免同一截图重复处理
 * - 30 秒时间窗（过滤旧截图）
 * - 关键词匹配（screenshot/截屏/截图）
 */
export class ScreenshotChannel {
  private processedUris = new Set<string>();
  private maxProcessed = DEDUP_CACHE_MAX;
  private listener: ((result: OcrProcessResult, event: ScreenshotEvent) => void) | null = null;

  constructor(
    private readonly ocrProcessor: OcrProcessor,
    private readonly nativeListener: ScreenshotListener | null = null,
  ) {}

  /** 注册截图事件回调（页面 OCR 处理后调用）。 */
  onScreenshot(handler: (result: OcrProcessResult, event: ScreenshotEvent) => void): void {
    this.listener = handler;
  }

  /** 启动监听（原生环境）。 */
  async start(): Promise<void> {
    if (!this.nativeListener) {
      logger.debug('screenshot', '原生截图监听未加载（可能为测试环境）');
      return;
    }
    await this.nativeListener.start(event => this.handleScreenshot(event));
  }

  /** 停止监听。 */
  async stop(): Promise<void> {
    await this.nativeListener?.stop();
  }

  /**
   * 处理单个截图事件（可手动调用，也可由原生监听触发）。
   * 返回 OCR 处理结果。
   */
  async handleScreenshot(event: ScreenshotEvent): Promise<OcrProcessResult> {
    // 1. 时间窗过滤（30 秒内的截图）
    if (Date.now() - event.timestamp > SCREENSHOT_TIME_WINDOW_MS) {
      logger.debug('screenshot', `忽略旧截图（超过30秒）: ${event.uri}`);
      return { event: null, layer: 'none', skipped: 'dedup' };
    }

    // 2. 关键词过滤（必须是截图）
    if (!this.isScreenshotUri(event.uri)) {
      logger.debug('screenshot', `非截图 URI，忽略: ${event.uri}`);
      return { event: null, layer: 'none', skipped: 'dedup' };
    }

    // 3. 去重（同一 URI 不重复处理）
    const uriHash = hash(event.uri);
    if (this.processedUris.has(uriHash)) {
      logger.debug('screenshot', `[跳过] URI 去重: ${event.uri}`);
      return { event: null, layer: 'none', skipped: 'dedup' };
    }
    this.processedUris.add(uriHash);
    if (this.processedUris.size > this.maxProcessed) {
      const first = this.processedUris.values().next().value;
      if (first) this.processedUris.delete(first);
    }

    // 4. OCR 处理
    const base64 = event.base64 ?? '';
    if (!base64) {
      logger.warn('screenshot', '截图无 base64 数据，跳过');
      return { event: null, layer: 'none' };
    }
    const result = await this.ocrProcessor.process(base64, event.packageName);

    // 5. 通知监听器
    if (this.listener && result.event) {
      this.listener(result, event);
    }
    return result;
  }

  /** 判断 URI 是否为截图（关键词匹配）。 */
  private isScreenshotUri(uri: string): boolean {
    return SCREENSHOT_KEYWORDS.some(kw => uri.toLowerCase().includes(kw.toLowerCase()));
  }

  /** 重置去重状态。 */
  reset(): void {
    this.processedUris.clear();
  }
}

/**
 * 模拟截图监听器（测试用，可手动触发事件）。
 */
export class SimulatedScreenshotListener implements ScreenshotListener {
  private listening = false;
  private handler: ((event: ScreenshotEvent) => void) | null = null;

  async start(handler: (event: ScreenshotEvent) => void): Promise<void> {
    this.handler = handler;
    this.listening = true;
  }
  async stop(): Promise<void> {
    this.listening = false;
    this.handler = null;
  }
  isListening(): boolean {
    return this.listening;
  }
  /** 测试辅助：模拟截图事件。 */
  simulate(event: ScreenshotEvent): void {
    this.handler?.(event);
  }
}
