/**
 * Excel 导出（plan.md「5.9 导出功能」）。
 *
 * 参考 BeeCount 的 Excel 导出：把交易列表导出为 .xlsx。
 *
 * Excel 生成通过注入抽象（生产用 xlsx 库，测试用 CSV 降级 + mock），
 * 数据转换为纯函数。
 */

import type { Transaction } from '../../domain/core/types';

/** Excel 工作簿抽象（生产用 xlsx 库）。 */
export interface ExcelWorkbook {
  /** 添加工作表。 */
  addSheet(name: string, rows: Record<string, unknown>[]): void;
  /** 写入文件，返回路径。 */
  write(filePath: string): Promise<string>;
  /** 写入并返回 base64（分享用）。 */
  writeBase64(): Promise<string>;
}

/** 交易 → Excel 行转换（纯函数）。 */
export interface TransactionRow {
  日期: string;
  摘要: string;
  收入: string;
  支出: string;
  账户: string;
  币种: string;
  标签: string;
  来源: string;
  [key: string]: string;  // 索引签名，允许赋值给 Record<string, unknown>
}

export function transactionToRow(t: Transaction): TransactionRow {
  const incomePosting = t.postings.find(p => p.account.startsWith('Income') && p.amount && parseFloat(p.amount) < 0);
  const expensePosting = t.postings.find(p => p.account.startsWith('Expenses') && p.amount && parseFloat(p.amount) > 0);
  const assetPosting = t.postings.find(p => p.account.startsWith('Assets'));
  return {
    日期: t.date.slice(0, 10),
    摘要: t.narration || t.payee || '',
    收入: incomePosting ? incomePosting.amount!.replace('-', '') : '',
    支出: expensePosting ? expensePosting.amount! : '',
    账户: expensePosting?.account ?? incomePosting?.account ?? assetPosting?.account ?? '',
    币种: expensePosting?.currency ?? incomePosting?.currency ?? assetPosting?.currency ?? 'CNY',
    标签: t.tags.map(tag => `#${tag}`).join(' '),
    来源: t.source,
  };
}

/** 批量转换。 */
export function transactionsToRows(transactions: Transaction[]): TransactionRow[] {
  return transactions.map(transactionToRow);
}

/**
 * 导出交易为 Excel。
 * @param transactions 交易列表
 * @param workbook Excel 工作簿（注入）
 * @param filePath 输出路径
 */
export async function exportToExcel(
  transactions: Transaction[],
  workbook: ExcelWorkbook,
  filePath: string,
): Promise<string> {
  const rows = transactionsToRows(transactions);
  workbook.addSheet('交易', rows);
  return workbook.write(filePath);
}

/** 导出为多工作表（交易 + 账户余额 + 分类统计）。 */
export async function exportToExcelMultiSheet(
  transactions: Transaction[],
  workbook: ExcelWorkbook,
  filePath: string,
): Promise<string> {
  // 工作表 1：交易明细
  workbook.addSheet('交易', transactionsToRows(transactions));

  // 工作表 2：账户余额
  const balances = new Map<string, { income: number; expense: number }>();
  for (const t of transactions) {
    for (const p of t.postings) {
      if (!p.amount) continue;
      const account = p.account;  // 完整账户名
      const cur = balances.get(account) ?? { income: 0, expense: 0 };
      const amt = parseFloat(p.amount);
      if (amt > 0) cur.income += amt;
      else cur.expense += Math.abs(amt);
      balances.set(account, cur);
    }
  }
  workbook.addSheet('账户余额', [...balances.entries()].map(([账户, b]) => ({
    账户,
    收入: b.income.toFixed(2),
    支出: b.expense.toFixed(2),
    净额: (b.income - b.expense).toFixed(2),
  })));

  return workbook.write(filePath);
}

/**
 * CSV 降级导出（无 xlsx 库时用，纯文本）。
 */
export function exportToCsv(transactions: Transaction[]): string {
  const header = '日期,摘要,收入,支出,账户,币种,标签,来源';
  const rows = transactionsToRows(transactions).map(r =>
    [r.日期, r.摘要, r.收入, r.支出, r.账户, r.币种, r.标签, r.来源]
      .map(v => `"${String(v).replace(/"/g, '""')}"`).join(','),
  );
  return [header, ...rows].join('\n');
}

/** 模拟 Excel 工作簿（测试用，记录写入内容）。 */
export class MockExcelWorkbook implements ExcelWorkbook {
  public sheets: { name: string; rows: Record<string, unknown>[] }[] = [];
  public writtenTo: string | null = null;

  addSheet(name: string, rows: Record<string, unknown>[]): void {
    this.sheets.push({ name, rows });
  }
  async write(filePath: string): Promise<string> {
    this.writtenTo = filePath;
    return filePath;
  }
  async writeBase64(): Promise<string> {
    return 'mock-base64';
  }
}
