import { pgQuery } from '../lib/postgres/client';
import {
  pgCreateBankReconciliationPeriod,
  pgBatchAddBankTransactions,
  pgAddLedgerTransaction,
} from '../lib/postgres/bank-reconciliation';
import {
  previewAutoMatchForPeriod,
  applyAutoMatchPreviewForPeriod,
} from '../lib/services/bank-reconciliation-auto-match';
import type {
  BankReconciliationPeriod,
  BankTransaction,
  LedgerTransaction,
} from '../lib/types';

const BANK_ACCOUNT_ID = 'bank-1776171260132-0';
const TEST_USER = 'test@system.local';

async function main() {
  try {
    const periodStart = '2024-02-01';
    const periodEnd = '2024-02-29';

    const cleanupRows = await pgQuery<{ id: string }>(
      `
      SELECT id
      FROM bank_reconciliation_periods
      WHERE bank_account_id = $1
        AND period_start_date = $2
        AND period_end_date = $3
      `,
      [BANK_ACCOUNT_ID, periodStart, periodEnd]
    );

    if (cleanupRows.rows.length > 0) {
      const ids = cleanupRows.rows.map((r) => r.id);
      const ledgerRows = await pgQuery<{ id: string }>(
        'SELECT id FROM ledger_transactions WHERE reconciliation_period_id = ANY($1::TEXT[])',
        [ids]
      );
      const ledgerIds = ledgerRows.rows.map((r) => r.id);
      if (ledgerIds.length > 0) {
        await pgQuery(
          'DELETE FROM bank_reconciliation_differences WHERE ledger_transaction_id = ANY($1::TEXT[])',
          [ledgerIds]
        );
      }
      await pgQuery('DELETE FROM bank_reconciliation_differences WHERE reconciliation_period_id = ANY($1::TEXT[])', [ids]);
      await pgQuery('DELETE FROM reconciliation_matches WHERE reconciliation_period_id = ANY($1::TEXT[])', [ids]);
      await pgQuery('DELETE FROM bank_transactions WHERE reconciliation_period_id = ANY($1::TEXT[])', [ids]);
      await pgQuery('DELETE FROM ledger_transactions WHERE reconciliation_period_id = ANY($1::TEXT[])', [ids]);
      await pgQuery('DELETE FROM bank_reconciliation_periods WHERE id = ANY($1::TEXT[])', [ids]);
    }

    const period = await pgCreateBankReconciliationPeriod({
      bankAccountId: BANK_ACCOUNT_ID,
      periodStartDate: periodStart,
      periodEndDate: periodEnd,
      statementStartBalance: 200000,
      statementEndBalance: 205000,
      status: 'draft',
      createdBy: TEST_USER,
    } as Omit<BankReconciliationPeriod, 'id' | 'createdAt' | 'updatedAt'>);

    await pgBatchAddBankTransactions([
      {
        reconciliationPeriodId: period.id,
        bankAccountId: BANK_ACCOUNT_ID,
        transactionDate: '2024-02-05',
        amount: 3000,
        direction: 'inward',
        description: 'Receipt INV-1001',
        bankReference: 'DEP-1001',
        type: 'transfer',
        currencyCode: 'USD',
      },
      {
        reconciliationPeriodId: period.id,
        bankAccountId: BANK_ACCOUNT_ID,
        transactionDate: '2024-02-10',
        amount: 1200,
        direction: 'outward',
        description: 'Check 7788',
        bankReference: 'CHK-7788',
        type: 'check',
        currencyCode: 'USD',
      },
    ] as Omit<BankTransaction, 'id' | 'createdAt' | 'updatedAt'>[]);

    await pgAddLedgerTransaction({
      bankAccountId: BANK_ACCOUNT_ID,
      journalEntryId: 'je-prev-1',
      journalEntryLineIdx: 0,
      transactionDate: '2024-02-05',
      amount: 3000,
      direction: 'inward',
      description: 'Receipt INV-1001',
      referenceType: 'invoice',
      referenceId: 'inv-1001',
      postingStatus: 'posted',
      reconciliationStatus: 'unreconciled',
      currencyCode: 'USD',
      fxRate: 1,
    } as Omit<LedgerTransaction, 'id' | 'createdAt' | 'updatedAt'>);

    await pgAddLedgerTransaction({
      bankAccountId: BANK_ACCOUNT_ID,
      journalEntryId: 'je-prev-2',
      journalEntryLineIdx: 1,
      transactionDate: '2024-02-10',
      amount: 1200,
      direction: 'outward',
      description: 'Check 7788',
      referenceType: 'check',
      referenceId: 'chk-7788',
      postingStatus: 'posted',
      reconciliationStatus: 'unreconciled',
      currencyCode: 'USD',
      fxRate: 1,
    } as Omit<LedgerTransaction, 'id' | 'createdAt' | 'updatedAt'>);

    const preview = await previewAutoMatchForPeriod(period.id, 80);
    console.log(`Preview suggestions: ${preview.suggestions.length}`);

    const applyResult = await applyAutoMatchPreviewForPeriod(
      period.id,
      TEST_USER,
      preview.suggestions.map((s) => ({
        bankTransactionId: s.bankTransactionId,
        ledgerTransactionId: s.ledgerTransactionId,
        matchType: s.matchType,
        matchConfidence: s.matchConfidence,
      }))
    );

    console.log(`Applied: ${applyResult.appliedCount}`);
    console.log(`Skipped: ${applyResult.skippedCount}`);
    console.log(`Final matchedCount: ${applyResult.matchedCount}`);

    if (applyResult.appliedCount < 1) {
      throw new Error('Expected at least one applied suggestion');
    }

    console.log('Preview + Apply flow test passed');
    process.exit(0);
  } catch (error) {
    console.error(error instanceof Error ? error.message : error);
    process.exit(1);
  }
}

main();
