/**
 * 自动化管道协调器（plan.md「3.x 自动记账统一管理」JS 接线）。
 *
 * 截图/无障碍事件是原始图片（base64），不是 ImportedEvent。
 * 需要经过 OcrProcessor（Layer1 规则 → Layer2 OCR → Layer3 AI Vision）
 * 才能转换为可入库的账单事件。
 *
 * 本模块提供单例 OcrProcessor + 统一的截图事件处理入口，
 * 供 _layout.tsx 的 DeviceEventEmitter 监听器调用。
 */

import { OcrProcessor } from '../../domain/pipeline/ocrProcessor';
import { buildAndSaveTransaction } from '../../domain/transaction/transactionBuilder';
import { dedupFingerprint } from '../../domain/transaction/dedup';
import type { OcrProcessResult } from '../../domain/pipeline/ocrProcessor';
import { getNativeOcrBridge } from '../ocr/ocrBridge';
import { AiVisionProcessor } from '../ocr/AiVisionProcessor';
import type { AiVisionProvider } from '../../domain/pipeline/ocrProcessor';
import { useSettingsStore } from '../../store/settingsStore';
import { useNumpadUiStore } from '../../store/numpadUiStore';
import { logger } from '../../utils/logger';
import { sanitizeLogText } from '../../utils/sanitize';
import { Alert, AppState, DeviceEventEmitter } from 'react-native';
import { useLedgerStore } from '../../store/ledgerStore';
import { useMetadataStore } from '../../store/metadataStore';
import { sharedPipeline } from '../../domain/pipeline/pipelineSingleton';
import type { ImportedEvent } from '../../domain/core/types';
import { getAccessibilityBridge } from './accessibilityBridge';
import { t } from '../../i18n';

// 从拆分模块导入
import {
  pendingDrafts,
  evictOldestPendingDraft,
  buildFloatingBillData,
} from './floatingBillManager';
import {
  addProcessedTxKey,
  hasProcessedTxKey,
  removeProcessedTxKey,
  clearProcessedTxKeys,
} from '../security/txKeyStore';
import { parseAccessibilityTexts } from './accessibilityParser';

// ---- 向后兼容 re-export（_layout.tsx 等调用方使用） ----
export { pendingDrafts } from './floatingBillManager';
export { loadProcessedTxKeys } from '../security/txKeyStore';
export type { PendingDraft } from './floatingBillManager';

// ---- 全局监听器 ----
const BILLING_LISTENER_KEY = 'billingConfirmed';
/** 浮窗草稿超时时间（毫秒）：超时未确认则自动清理。 */
const FLOATING_DRAFT_TIMEOUT_MS = 120_000;
let billingListener: { remove(): void } | null = null;

async function handleBillingConfirmed(res: { draftId?: string; confirmed?: boolean; amount?: string; time?: string; direction?: string; merchant?: string; narration?: string; category?: string; account?: string; currency?: string }) {
  const { draftId, confirmed } = res;
  if (!draftId) return;

  if (!confirmed) {
    const pending = pendingDrafts.get(draftId);
    if (pending) {
      const { event } = pending;
      const txKey = dedupFingerprint(event);
      removeProcessedTxKey(txKey);
      pendingDrafts.delete(draftId);
      logger.info('automationPipeline', `[浮窗忽略] 用户取消入账，清除去重缓存: ${txKey}`);
    }
    return;
  }

  const pending = pendingDrafts.get(draftId);
  if (pending) {
    pendingDrafts.delete(draftId);
  } else {
    logger.info('automationPipeline', `[浮窗入账] 未找到待挂起的确认交易草稿，启用容错备选参数写入。draftId: ${draftId}`);
  }

  try {
    // 容错路径数据校验：确保关键字段存在
    if (!pending && !res.amount) {
      logger.error('automationPipeline', `[浮窗入账] 容错路径缺少关键字段(amount)，放弃写入。draftId: ${draftId}`);
      return;
    }
    const draftDate = pending?.draft?.date || (res.time ? res.time.split(' ')[0] : new Date().toISOString().split('T')[0]);
    const currency = res.currency || pending?.event?.currency || 'CNY';
    const direction = (res.direction || pending?.event?.direction || 'expense') as 'expense' | 'income' | 'transfer';
    const tags = pending?.draft?.tags || undefined;
    const links = pending?.draft?.links || undefined;
    const metadata = pending?.draft?.metadata || undefined;

    const origPayee = pending?.draft?.payee ?? pending?.event?.counterparty ?? '';
    const origCategory = pending?.draft?.postings[1]?.account ?? 'Expenses:未分类';
    const origSource = pending?.draft?.postings[0]?.account ?? 'Assets:未知';
    const origAmount = (pending?.draft?.postings[0]?.amount ?? pending?.event?.amount ?? '0').replace(/^-/, '');
    const origDirection = pending?.event?.direction ?? 'expense';

    const userPayee = res.merchant || origPayee;
    const userCategory = res.category || origCategory;
    const userSource = res.account || origSource;
    const userAmount = res.amount || origAmount;
    const userDirection = direction;

    const isCategoryChanged = userCategory !== origCategory;
    const isPayeeChanged = userPayee !== origPayee;
    const isAmountChanged = userAmount !== origAmount;
    const isSourceChanged = userSource !== origSource;
    const isDirectionChanged = userDirection !== origDirection;

    if (isCategoryChanged || isPayeeChanged || isAmountChanged || isSourceChanged || isDirectionChanged) {
      // 跨切面分析 tag：专门追踪用户修正行为，独立于模块 tag 便于日志筛选
      logger.info('userCorrection', `[用户修正识别/分类] 推荐识别 vs 用户修改比对:`, {
        source: pending?.event?.raw?.source ?? 'unknown',
        original: { payee: origPayee, category: origCategory, sourceAccount: origSource, amount: origAmount, direction: origDirection },
        corrected: { payee: userPayee, category: userCategory, sourceAccount: userSource, amount: userAmount, direction: userDirection },
        changes: { categoryChanged: isCategoryChanged, payeeChanged: isPayeeChanged, amountChanged: isAmountChanged, sourceChanged: isSourceChanged, directionChanged: isDirectionChanged },
      });
    }

    await buildAndSaveTransaction({
      date: draftDate,
      amount: res.amount ?? '0',
      payee: res.merchant || undefined,
      narration: res.narration || undefined,
      categoryAccount: res.category ?? 'Expenses:未分类',
      sourceAccount: res.account ?? 'Assets:未知',
      direction,
      currency,
      tags,
      links,
      metadata,
    }, useLedgerStore.getState(), false);
    logger.info('automationPipeline', `[浮窗入账] 交易已成功在后台确认入账：${res.amount ?? '0'} ${currency}`);
  } catch (e) {
    logger.error('automationPipeline', `[浮窗入账] 后台确认入账失败 (draftId: ${draftId})`, e);
  }
}

function ensureBillingListener(): void {
  if (billingListener) return;
  // 热重载时先移除旧监听器，防止重复注册
  DeviceEventEmitter.removeAllListeners(BILLING_LISTENER_KEY);
  billingListener = DeviceEventEmitter.addListener(BILLING_LISTENER_KEY, handleBillingConfirmed);
}

// ---- OcrProcessor 单例 ----

let ocrProcessor: OcrProcessor | null = null;
let lastSettingsRef: ReturnType<typeof useSettingsStore.getState> | null = null;

function getOcrProcessor(): OcrProcessor | null {
  // 检查配置是否变更，变更时重建处理器（使用引用比较避免每次拼接字符串）
  const settings = useSettingsStore.getState();
  if (ocrProcessor && settings === lastSettingsRef) return ocrProcessor;
  lastSettingsRef = settings;

  try {
    // P8：从 settingsStore 读取 OCR 模型目录，传入原生引擎从 filesystem 加载模型
    const ocrEngine = getNativeOcrBridge(settings.ocrModelDir || undefined);
    // settings already obtained above for config check

    let aiProvider: AiVisionProvider | undefined;
    if (settings.aiEnabled && settings.aiApiKey && settings.aiBaseUrl) {
      aiProvider = new AiVisionProcessor({
        enabled: true,
        apiUrl: settings.aiBaseUrl,
        apiKey: settings.aiApiKey,
        model: settings.aiModel || 'glm-4v-flash',
      });
    }

    ocrProcessor = new OcrProcessor(ocrEngine, aiProvider, {
      layer1Enabled: settings.layer1RuleEnabled,
      layer2Enabled: settings.layer2OcrEnabled,
      layer3Enabled: settings.layer3AiEnabled,
      landscapeDnd: false,
    });
    return ocrProcessor;
  } catch (e) {
    logger.warn('automationPipeline', `OcrProcessor 初始化失败: ${e}`);
    return null;
  }
}

// ---- 截图处理 ----

export interface NativeScreenshotEvent {
  base64?: string;
  uri?: string;
  packageName?: string;
  timestamp?: number;
  displayName?: string;
}

export async function processScreenshotEvent(event: NativeScreenshotEvent): Promise<OcrProcessResult | null> {
  const base64 = event.base64;
  if (!base64) {
    logger.warn('automationPipeline', '截图事件无 base64 数据，跳过');
    return null;
  }

  const processor = getOcrProcessor();
  if (!processor) {
    logger.warn('automationPipeline', 'OcrProcessor 不可用，跳过截图处理');
    return null;
  }

  try {
    const result = await processor.process(base64, event.packageName, false);
    if (result.event) {
      logger.debug('automationPipeline', `截图识别成功 (${result.layer})`, { ocrText: sanitizeLogText(result.ocrText ?? '') });
      await handleIncomingBillEvent('screenshot', result.event, result.ocrText ?? '');
    } else if (result.skipped === 'ocr-error') {
      // OCR 引擎故障（模型未加载/原生异常），区别于"识别了但不是账单"
      logger.error('automationPipeline', `截图 OCR 引擎故障 (layer=${result.layer})，本次跳过，下次截图将重试`, { ocrText: sanitizeLogText(result.ocrText ?? '') });
    } else if (result.skipped === 'ocr-empty') {
      // OCR 引擎返回空文本（全空白），常见于 WebView 未渲染完/反截屏，区别于"有内容但不是账单"
      logger.debug('automationPipeline', `截图 OCR 返回空文本 (layer=${result.layer})，可能页面未渲染完成或被反截屏，本次跳过。`);
    } else {
      logger.debug('automationPipeline', `截图未识别为账单 (layer=${result.layer}, skipped=${result.skipped ?? 'none'})`, { ocrText: sanitizeLogText(result.ocrText ?? '') });
    }
    return result;
  } catch (e) {
    logger.error('automationPipeline', `[截图处理异常] 包名: ${event.packageName ?? '未知'}`, e);
    return null;
  }
}

// ---- 实时账单处理（前台弹窗/后台浮窗） ----

export async function handleIncomingBillEvent(source: string, event: ImportedEvent, rawText: string) {
  const ledger = useLedgerStore.getState().ledger;
  if (!ledger) {
    logger.warn('automationPipeline', '账本未加载，跳过实时入账处理');
    return;
  }

  const txKey = dedupFingerprint(event);
  if (hasProcessedTxKey(txKey)) {
    logger.info('automationPipeline', `[实时入账去重] 过滤相同交易: ${txKey} (当前运行已处理过，拦截弹窗)`);
    return;
  }
  addProcessedTxKey(txKey);

  const rules = useMetadataStore.getState().rules;
  const categories = useMetadataStore.getState().categories;
  const history = ledger.transactions;
  const dedupConfig = useSettingsStore.getState().dedupConfig;
  const transferConfig = useSettingsStore.getState().transferConfig;

  try {
    const result = await sharedPipeline.process([event], {
      ledger,
      rules,
      categories,
      history,
      dedupConfig,
      transferConfig,
    });

    const draft = result.drafts[0];
    if (!draft) {
      logger.info('automationPipeline', `[实时入账] 处理结束，事件已被去重过滤 (事件ID: ${event.id}, 时间: ${event.occurredAt}, 金额: ${event.amount} ${event.currency}, 对方: "${event.counterparty || '无'}")`);
      return;
    }

    const amount = (draft.draft.postings[0]?.amount ?? '0').replace(/^-/, '');
    const currency = draft.draft.postings[0]?.currency ?? 'CNY';
    const sourceAccount = draft.draft.postings[0]?.account ?? 'Assets:Unknown';
    const targetAccount = draft.draft.postings[1]?.account ?? 'Expenses:未分类';

    logger.info('automationPipeline',
      `[新账单] ${amount} ${currency} → ${targetAccount} | ${event.counterparty || '未知'} | ${source}`,
      {
        source,
        recognized: {
          time: event.occurredAt,
          amount: `${event.amount} ${event.currency}`,
          direction: event.direction === 'income' ? '收入' : '支出',
          counterparty: event.counterparty || '无',
          memo: event.memo || '无',
        },
        draft: {
          date: draft.draft.date,
          payee: draft.draft.payee || '无',
          narration: draft.draft.narration || '无',
          targetAccount,
          sourceAccount,
        },
      },
    );
    // 原始文本仅 DEBUG 级别输出（脱敏后），避免 INFO 日志膨胀
    logger.debug('automationPipeline', `[新账单原始文本] 来源: ${source}`, { raw: sanitizeLogText(rawText) });

    // 后台模式：浮窗
    if (AppState.currentState !== 'active') {
      logger.info('automationPipeline', `[实时入账] 检测到 App 处于后台，正在触发系统悬浮浮窗进行记账确认`);
      const bridge = getAccessibilityBridge();
      if (bridge) {
        const draftId = Math.random().toString(36).substring(2, 9) + Date.now().toString(36);
        try {
          const shortTargetAccount = targetAccount.split(':').pop() || targetAccount;
          const timeStr = draft.draft.date + ' ' + (draft.draft.narration || '');
          const { sortedCategories, sortedAccounts } = buildFloatingBillData(targetAccount, sourceAccount, ledger);

          evictOldestPendingDraft();
          pendingDrafts.set(draftId, { draft: draft.draft, event });

          await bridge.showFloatingBill(
            amount,
            draft.draft.payee || shortTargetAccount,
            timeStr,
            event.raw?.packageName || '',
            sortedCategories,
            sortedAccounts,
            event.direction || 'expense',
            currency,
            draftId,
          );

          setTimeout(() => {
            if (pendingDrafts.has(draftId)) {
              pendingDrafts.delete(draftId);
              // 超时未确认时同步清除去重缓存，允许后续相同交易重新触发
              const txKeyTimeout = dedupFingerprint(event);
              removeProcessedTxKey(txKeyTimeout);
              logger.info('automationPipeline', `[浮窗入账] 悬浮窗草稿超时未确认，已自动清理缓存并移除去重键, ID: ${draftId}`);
            }
          }, FLOATING_DRAFT_TIMEOUT_MS);
          return;
        } catch (err) {
          logger.error('automationPipeline', `[浮窗入账] 显示浮窗失败 (draftId: ${draftId})，降级拉起前台弹窗`, err);
        }
      }

      logger.info('automationPipeline', `[实时入账] 降级拉起 App 前台...`);
      const bridgeForFallback = getAccessibilityBridge();
      if (bridgeForFallback) {
        try {
          await bridgeForFallback.bringAppToForeground();
          await new Promise(resolve => setTimeout(resolve, 600));
        } catch (err) {
          logger.error('automationPipeline', '[实时入账] 拉起前台失败', err);
        }
      }
    }

    // 前台模式：弹窗
    const suspiciousWarn = event.raw?.['suspiciousAmount'];
    Alert.alert(
      t('automation.billDetectedTitle'),
      `${t('automation.billDetectedHeader')}\n` +
      (suspiciousWarn ? `⚠️ ${suspiciousWarn}\n\n` : '') +
      `${t('automation.billDetectedLineDate')}: ${draft.draft.date}\n` +
      `${t('automation.billDetectedLineMerchant')}: ${draft.draft.payee ?? t('automation.billDetectedNone')}\n` +
      `${t('automation.billDetectedLineAmount')}: ${amount} ${currency}\n` +
      `${t('automation.billDetectedLineCategory')}: ${targetAccount}\n` +
      `${t('automation.billDetectedLineAccount')}: ${sourceAccount}\n` +
      `${t('automation.billDetectedLineNarration')}: ${draft.draft.narration || t('automation.billDetectedNone')}\n\n` +
      t('automation.billDetectedPrompt'),
      [
        {
          text: t('automation.billDetectedReject'),
          style: 'cancel',
          onPress: () => {
            logger.info('automationPipeline', `[实时入账] 用户选择拒绝/丢弃交易`);
          }
        },
        {
          text: t('automation.billDetectedEdit'),
          onPress: () => {
            logger.info('automationPipeline', `[实时入账] 用户选择修改交易，跳转编辑页`);
            useNumpadUiStore.getState().open({
              draftJson: JSON.stringify(draft.draft)
            });
          }
        },
        {
          text: t('automation.billDetectedConfirm'),
          style: 'default',
          onPress: async () => {
            try {
              await useLedgerStore.getState().addTransaction(draft.draft);
              logger.info('automationPipeline', `[实时入账] 用户确认入账交易成功`);
            } catch (e) {
              logger.error('automationPipeline', `[实时入账] 用户确认入账失败`, e);
              Alert.alert('入账失败', e instanceof Error ? e.message : String(e));
            }
          }
        }
      ]
    );
  } catch (e) {
    logger.error('automationPipeline', `[实时入账处理异常] 来源: ${source}, 事件ID: ${event.id}`, e);
  }
}

// ---- 无障碍文本解析（委托给 accessibilityParser） ----

export async function parseAndProcessAccessibilityTexts(texts: string[], packageName: string): Promise<boolean> {
  const event = parseAccessibilityTexts(texts, packageName);

  if (event) {
    const txKey = dedupFingerprint(event);
    if (hasProcessedTxKey(txKey)) {
      logger.info('automationPipeline', `[直接文本解析去重] 过滤相同交易: ${txKey} (已确认/忽略过，跳过浮窗)`);
      return true;
    }

    logger.debug('automationPipeline', `[直接文本解析成功] 进入账单管道`);
    await handleIncomingBillEvent('accessibility_nodes', event, JSON.stringify(texts));
    return true;
  }

  return false;
}

// ---- 重置 ----

export function resetAutomationPipeline(): void {
  ocrProcessor?.reset();
  ocrProcessor = null;
  clearProcessedTxKeys();
  if (billingListener) {
    billingListener.remove();
    billingListener = null;
  }
}

/**
 * 注册全局 billingConfirmed 监听器（幂等）。
 * 由 _layout.tsx 的 useEffect 调用，而非模块顶层，避免热重载时泄漏。
 */
export function ensureBillingListenerRegistered(): void {
  ensureBillingListener();
}

/** 移除全局 billingConfirmed 监听器（卸载时调用）。 */
export function removeBillingListener(): void {
  if (billingListener) {
    billingListener.remove();
    billingListener = null;
  }
}
