import { detectDirection } from '../core/constants';
import { negateDecimal } from '../core/decimal';
import { hash } from '../core/ledger';
import type { Direction, ImportedEvent } from '../core/types';

export type StatementAdapter = 'alipay-csv-v1' | 'wechat-csv-v1' | 'bank-csv-v1';
type Row = Record<string, string>;

const first = (row: Row, keys: string[]) => keys.map(key => row[key]).find(Boolean)?.trim() ?? '';

function parseCsv(content: string): Row[] {
  const cleanContent = content.replace(/^\uFEFF/, '');
  const rows: string[][] = [];
  let currentRow: string[] = [];
  let currentCell = '';
  let inQuotes = false;

  for (let i = 0; i < cleanContent.length; i++) {
    const ch = cleanContent[i];
    if (inQuotes) {
      if (ch === '"') {
        if (i + 1 < cleanContent.length && cleanContent[i + 1] === '"') {
          currentCell += '"';
          i++;
        } else {
          inQuotes = false;
        }
      } else {
        currentCell += ch;
      }
    } else {
      if (ch === '"') {
        inQuotes = true;
      } else if (ch === ',') {
        currentRow.push(currentCell.trim());
        currentCell = '';
      } else if (ch === '\n' || ch === '\r') {
        if (ch === '\r' && cleanContent[i + 1] === '\n') {
          i++;
        }
        currentRow.push(currentCell.trim());
        currentCell = '';
        if (currentRow.some(Boolean)) {
          rows.push(currentRow);
        }
        currentRow = [];
      } else {
        currentCell += ch;
      }
    }
  }

  if (currentCell || currentRow.length > 0) {
    currentRow.push(currentCell.trim());
    if (currentRow.some(Boolean)) {
      rows.push(currentRow);
    }
  }

  const headerRowIndex = rows.findIndex(row =>
    row.some(cell => /时间|date/i.test(cell)) &&
    row.some(cell => /金额|amount/i.test(cell))
  );
  if (headerRowIndex === -1) {
    throw new Error('未找到账单表头');
  }

  const headers = rows[headerRowIndex].map(h => h.replace(/^"|"$/g, ''));
  const dataRows = rows.slice(headerRowIndex + 1);

  return dataRows.map(row => {
    return Object.fromEntries(headers.map((header, index) => [header, row[index] ?? '']));
  }).filter(row => Object.values(row).some(Boolean));
}
/** CSV 方向判定：先尝试统一方向检测（组合 flow+txType），再回退到金额符号与 flow 关键词。 */
function direction(flow: string, txType: string, amount: string): Direction {
  const combined = `${flow}|${txType}`;
  const detected = detectDirection(combined, 'income');
  if (detected !== 'income') return detected;
  // CSV 特有回退：金额为负 或 flow 含支出关键词 → expense
  return amount.startsWith('-') || /支出|付款|消费/i.test(flow) ? 'expense' : 'income';
}
function mapRowToEvent(row: Row, index: number): ImportedEvent {
  let amount = first(row, ['金额(元)', '金额', '交易金额', '金额（元）', 'Amount', 'amount']).replace(/[¥￥\s]/g, '').replace(/,/g, '');
  const flow = first(row, ['收/支', '收支类型', '资金方向', 'Type', 'type']);
  const txType = first(row, ['交易类型', '商品分类', '交易分类']);
  if (!amount) throw new Error(`第 ${index + 1} 行缺少金额`);
  if (/支出|付款|消费|转出/i.test(flow) && !amount.startsWith('-')) amount = negateDecimal(amount);
  const occurredAt = first(row, ['交易创建时间', '交易时间', '交易日期', '时间', 'Date', 'date']).replace(/[/.]/g, '-').slice(0, 19);
  const externalId = first(row, ['交易订单号', '交易单号', '商户订单号', '流水号', 'Transaction ID', 'id']);
  const counterparty = first(row, ['交易对方', '交易对手', '对方账户', '商户名称', 'Counterparty', 'merchant']);
  const rawMemo = first(row, ['商品', '商品说明', '商品名称', '备注', '交易描述', 'Memo', 'description']);
  const category = first(row, ['商品分类', '交易分类', '分类', 'Category', 'category']);
  const method = first(row, ['收/付款方式', '收付款方式', '支付方式', 'Payment Method', 'method']);
  const memo = [category, rawMemo, method ? `[${method}]` : ''].filter(s => s && s.trim() !== '').join(' - ');
  const eventDirection = direction(flow, txType, amount);
  const id = externalId ? `csv:${externalId}` : `fp-${hash([occurredAt, amount, eventDirection, counterparty, memo].join('|'))}`;
  const isDateValid = /^\d{4}-\d{2}-\d{2}/.test(occurredAt);
  const finalOccurredAt = isDateValid ? occurredAt : new Date().toISOString().slice(0, 19).replace('T', ' ');
  const currency = first(row, ['币种', 'Currency', 'currency']) || 'CNY';
  return { id, occurredAt: finalOccurredAt, amount, currency, direction: eventDirection, counterparty, memo, externalId: externalId || undefined, raw: row };
}

export function importStatement(content: string, _adapter: StatementAdapter): ImportedEvent[] {
  const rows = parseCsv(content);
  return rows.map((row, index) => mapRowToEvent(row, index));
}
export function deduplicate(events: ImportedEvent[], existingIds: Set<string>): { accepted: ImportedEvent[]; duplicates: ImportedEvent[] } {
  const seen = new Set(existingIds); const accepted: ImportedEvent[] = []; const duplicates: ImportedEvent[] = [];
  for (const event of events) { if (seen.has(event.id)) duplicates.push(event); else { seen.add(event.id); accepted.push(event); } }
  return { accepted, duplicates };
}
