import { describe, expect, it, beforeEach } from 'vitest';
import { useLedgerStore } from '../src/store/ledgerStore';
import { MemoryBackend } from '../src/domain/mobileStore';
import type { LedgerFile } from '../src/domain/types';

const sampleLedger: LedgerFile = {
  path: 'main.bean',
  content: `option "operating_currency" "CNY"
2026-01-01 open Assets:Alipay CNY
2026-01-01 open Expenses:Food CNY
2026-01-01 open Expenses:Uncategorized CNY
2026-01-01 open Income:Uncategorized CNY
include "mobile.bean"
`,
};

const usdLedger: LedgerFile = {
  path: 'main.bean',
  content: `option "operating_currency" "USD"
2026-01-01 open Assets:Bank USD
2026-01-01 open Expenses:Food USD
include "mobile.bean"
`,
};

beforeEach(() => {
  useLedgerStore.getState().reset();
});

describe('ledgerStore 写操作', () => {
  it('autoOpenAccounts 跳过已 open 的账户（去重）', async () => {
    await useLedgerStore.getState().loadLedger([sampleLedger], new MemoryBackend());
    const before = useLedgerStore.getState().mobileBean;

    // Assets:Alipay 已存在 → 应跳过
    await useLedgerStore.getState().autoOpenAccounts(['Assets:Alipay', 'Assets:NewAccount']);
    const after = useLedgerStore.getState().mobileBean;

    // 只新增 Assets:NewAccount
    expect(after).toContain('Assets:NewAccount');
    // 不应添加重复的 open Assets:Alipay（只保留原有的）
    const openAlipayCount = (after.match(/open Assets:Alipay/g) ?? []).length;
    expect(openAlipayCount).toBe(1); // 只有原始的一条，没有重复添加
  });

  it('autoOpenAccounts 对已全部 open 的列表是 no-op', async () => {
    await useLedgerStore.getState().loadLedger([sampleLedger], new MemoryBackend());
    const before = useLedgerStore.getState().mobileBean;

    await useLedgerStore.getState().autoOpenAccounts(['Assets:Alipay']);
    const after = useLedgerStore.getState().mobileBean;

    expect(after).toBe(before); // 无变化
  });

  it('autoOpenAccounts 使用 ledger 的 operating_currency', async () => {
    await useLedgerStore.getState().loadLedger([usdLedger], new MemoryBackend());
    await useLedgerStore.getState().autoOpenAccounts(['Assets:NewUSD']);
    const after = useLedgerStore.getState().mobileBean;

    // 应写 USD 而非 CNY
    expect(after).toContain('open Assets:NewUSD USD');
    expect(after).not.toContain('open Assets:NewUSD CNY');
  });

  it('adjustAccountBalance 使用 ledger 的 operating_currency', async () => {
    await useLedgerStore.getState().loadLedger([usdLedger], new MemoryBackend());
    await useLedgerStore.getState().adjustAccountBalance('Assets:Bank', '5000', '2026-07-15');
    const after = useLedgerStore.getState().mobileBean;

    // balance 断言应使用 USD
    expect(after).toContain('balance Assets:Bank 5000 USD');
  });

  it('appendTransactionsBatch 在锁内拼接多笔交易', async () => {
    await useLedgerStore.getState().loadLedger([sampleLedger], new MemoryBackend());
    const before = useLedgerStore.getState().mobileBean;

    await useLedgerStore.getState().appendTransactionsBatch([
      { date: '2026-07-10', narration: '午餐', postings: [{ account: 'Assets:Alipay', amount: '-20', currency: 'CNY' }, { account: 'Expenses:Food', amount: '20', currency: 'CNY' }] },
      { date: '2026-07-11', narration: '晚餐', postings: [{ account: 'Assets:Alipay', amount: '-30', currency: 'CNY' }, { account: 'Expenses:Food', amount: '30', currency: 'CNY' }] },
    ]);

    const after = useLedgerStore.getState().mobileBean;
    expect(after).toContain('午餐');
    expect(after).toContain('晚餐');
    expect(after.length).toBeGreaterThan(before.length);
  });

  it('并发 addTransaction + autoOpenAccounts 不丢失数据', async () => {
    await useLedgerStore.getState().loadLedger([sampleLedger], new MemoryBackend());

    // 并发执行：添加交易 + 自动开户
    await Promise.all([
      useLedgerStore.getState().addTransaction({
        date: '2026-07-10', narration: '交易A',
        postings: [{ account: 'Assets:Alipay', amount: '-10', currency: 'CNY' }, { account: 'Expenses:Food', amount: '10', currency: 'CNY' }],
      }),
      useLedgerStore.getState().autoOpenAccounts(['Assets:NewAcct']),
    ]);

    const after = useLedgerStore.getState().mobileBean;
    // 两者都应存在（互斥锁保证了不丢失）
    expect(after).toContain('交易A');
    expect(after).toContain('Assets:NewAcct');
  });

  it('并发两笔 addTransaction 都保留', async () => {
    await useLedgerStore.getState().loadLedger([sampleLedger], new MemoryBackend());

    await Promise.all([
      useLedgerStore.getState().addTransaction({
        date: '2026-07-10', narration: '交易1',
        postings: [{ account: 'Assets:Alipay', amount: '-5', currency: 'CNY' }, { account: 'Expenses:Food', amount: '5', currency: 'CNY' }],
      }),
      useLedgerStore.getState().addTransaction({
        date: '2026-07-10', narration: '交易2',
        postings: [{ account: 'Assets:Alipay', amount: '-8', currency: 'CNY' }, { account: 'Expenses:Food', amount: '8', currency: 'CNY' }],
      }),
    ]);

    const txns = useLedgerStore.getState().ledger!.transactions;
    expect(txns).toHaveLength(2);
    expect(txns.map(t => t.narration).sort()).toEqual(['交易1', '交易2']);
  });
});
