import type { LedgerIndex, Posting, TransactionDraft } from '../core/types';
import { parseDecimal } from '../core/decimal';

export interface DraftInput {
  date: string;
  amount: string;          // 纯数字字符串 (例如 "89.30")
  payee?: string;          // 交易对手
  narration?: string;      // 描述/备注
  categoryAccount: string; // 费用科目 (Expenses) 或 目标账户 (Target Account)
  sourceAccount: string;   // 资金账户 (Assets/Liabilities)
  direction: 'income' | 'expense' | 'transfer';
  currency?: string;       // 币种，默认为 "CNY"
  tags?: string[];
  links?: string[];
  metadata?: Record<string, string>;
}

/** 事务存储抽象（供 buildAndSaveTransaction 使用，保持领域层纯函数）。 */
export interface TransactionStore {
  ledger: LedgerIndex | null;
  autoOpenAccounts(accounts: string[]): Promise<void>;
  addTransaction(draft: TransactionDraft, dedupConfig?: unknown, force?: boolean): Promise<unknown>;
}

export function buildPostings(
  direction: 'income' | 'expense' | 'transfer',
  sourceAccount: string,
  categoryAccount: string,
  amount: string,
  currency: string
): Posting[] {
  if (direction === 'expense') {
    return [
      { account: sourceAccount, amount: `-${amount}`, currency },
      { account: categoryAccount, amount, currency },
    ];
  } else if (direction === 'income') {
    return [
      { account: sourceAccount, amount, currency },
      { account: categoryAccount, amount: `-${amount}`, currency },
    ];
  } else {
    return [
      { account: sourceAccount, amount: `-${amount}`, currency },
      { account: categoryAccount, amount, currency },
    ];
  }
}

/**
 * 统一的简易模式交易构建与保存函数。
 * 供前台"记一笔" (new.tsx) 的简单模式和后台无障碍账单事件监听器共同使用，实现逻辑的一致性。
 */
export async function buildAndSaveTransaction(input: DraftInput, store: TransactionStore, force?: boolean): Promise<void> {
  const amt = input.amount.trim();
  if (!amt) {
    throw new Error('金额不能为空');
  }

  try {
    const parsed = parseDecimal(amt);
    if (parsed.coefficient <= 0n) {
      throw new Error('金额数值必须大于 0');
    }
  } catch (e) {
    if (e instanceof Error && e.message === '金额数值必须大于 0') throw e;
    throw new Error('金额数值必须大于 0');
  }

  // 1. 规范化日期格式，将年/月/日、斜杠、点号替换为连字符并自动补零（支持 2026/7/18、2026年7月18日等）
  let normalizedDate = input.date
    .replace(/[年]/g, '-')
    .replace(/[月]/g, '-')
    .replace(/[日]/g, '')
    .replace(/[/.]/g, '-')
    .trim();
  const dateParts = normalizedDate.split('-');
  if (dateParts.length === 3) {
    const y = dateParts[0];
    const m = dateParts[1].padStart(2, '0');
    const d = dateParts[2].padStart(2, '0');
    normalizedDate = `${y}-${m}-${d}`;
  }
  if (!/^\d{4}-\d{2}-\d{2}$/.test(normalizedDate)) {
    throw new Error('日期格式不正确，请输入标准格式（如 YYYY-MM-DD）');
  }

  const currency = input.currency || 'CNY';

  // 2. 自动开户容错：如果账本中不存在对应账户，自动调用 autoOpenAccounts 写入 open 指令
  const ledger = store.ledger;
  if (ledger) {
    const unopened: string[] = [];
    if (input.sourceAccount && !ledger.accounts.has(input.sourceAccount)) {
      unopened.push(input.sourceAccount);
    }
    if (input.categoryAccount && !ledger.accounts.has(input.categoryAccount)) {
      unopened.push(input.categoryAccount);
    }
    if (unopened.length > 0) {
      await store.autoOpenAccounts(unopened);
    }
  }

  // 根据交易方向，自动构建标准的复式记账 postings
  const postings = buildPostings(input.direction, input.sourceAccount, input.categoryAccount, amt, currency);

  const draft: TransactionDraft = {
    date: normalizedDate,
    payee: input.payee?.trim() || undefined,
    narration: input.narration?.trim() || (
      input.direction === 'expense' ? '支出交易' :
      input.direction === 'income' ? '收入交易' :
      '转账交易'
    ),
    postings,
    tags: input.tags,
    links: input.links,
    metadata: input.metadata,
  };

  // 调用统一的 ledgerStore 写入 Beancount 本地存储
  await store.addTransaction(draft, undefined, force);
}
