import { NextRequest, NextResponse } from 'next/server';
import {
  pgGetBankReconciliationPeriodById,
  pgGetBankTransactionsForPeriod,
  pgGetReconciliationMatchesForPeriod,
  pgGetAllLedgerTransactionsForBankAccount,
} from '@/lib/postgres/bank-reconciliation';

export type ReconciliationSummary = {
  periodId: string;
  // Bank Statement side
  statementOpeningBalance: number;
  statementClosingBalance: number;
  totalBankInflows: number;
  totalBankOutflows: number;
  clearedBankInflows: number;
  clearedBankOutflows: number;
  unmatchedBankInflows: number;  // bank credits not in books
  unmatchedBankOutflows: number; // bank debits not in books (fees, charges)
  // Timing differences
  depositsInTransit: number;    // ledger inflows not yet in bank
  outstandingChecks: number;    // ledger outflows not yet cleared
  // Balances
  adjustedBankBalance: number;  // closingBalance + depositsInTransit - outstandingChecks
  adjustedBookBalance: number;  // closingBalance + unmatchedBankInflows - unmatchedBankOutflows
  difference: number;           // adjustedBankBalance - adjustedBookBalance
  // Counts
  totalBankTransactions: number;
  matchedBankTransactions: number;
  unmatchedBankTransactions: number;
  totalLedgerTransactions: number;
  matchedLedgerTransactions: number;
  unmatchedLedgerTransactions: number;
  matchRate: number; // percentage
};

export async function GET(
  _req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id: periodId } = await params;

    const period = await pgGetBankReconciliationPeriodById(periodId);
    if (!period) {
      return NextResponse.json({ error: 'Period not found' }, { status: 404 });
    }

    const [bankTransactions, matches, allLedger] = await Promise.all([
      pgGetBankTransactionsForPeriod(periodId),
      pgGetReconciliationMatchesForPeriod(periodId),
      pgGetAllLedgerTransactionsForBankAccount(period.bankAccountId),
    ]);

    // Filter ledger to period date range
    const ledgerTransactions = allLedger.filter((lt) => {
      return lt.transactionDate >= period.periodStartDate &&
             lt.transactionDate <= period.periodEndDate;
    });

    const matchedBankIds = new Set(matches.map((m) => m.bankTransactionId));
    const matchedLedgerIds = new Set(matches.flatMap((m) => m.ledgerTransactionIds));

    // Bank side
    let totalBankInflows = 0;
    let totalBankOutflows = 0;
    let clearedBankInflows = 0;
    let clearedBankOutflows = 0;
    let unmatchedBankInflows = 0;
    let unmatchedBankOutflows = 0;

    for (const bt of bankTransactions) {
      const isInward = bt.direction === 'inward' || bt.direction === 'debit';
      const isMatched = matchedBankIds.has(bt.id);
      if (isInward) {
        totalBankInflows += bt.amount;
        if (isMatched) clearedBankInflows += bt.amount;
        else unmatchedBankInflows += bt.amount;
      } else {
        totalBankOutflows += bt.amount;
        if (isMatched) clearedBankOutflows += bt.amount;
        else unmatchedBankOutflows += bt.amount;
      }
    }

    // Ledger side (timing differences)
    let depositsInTransit = 0;
    let outstandingChecks = 0;
    let matchedLedgerCount = 0;

    for (const lt of ledgerTransactions) {
      const isInward = lt.direction === 'inward' || lt.direction === 'credit';
      const isMatched = matchedLedgerIds.has(lt.id);
      if (isMatched) {
        matchedLedgerCount++;
      } else {
        if (isInward) depositsInTransit += lt.amount;
        else outstandingChecks += lt.amount;
      }
    }

    const statementClosingBalance = period.statementEndBalance || 0;
    const statementOpeningBalance = period.statementStartBalance || 0;

    const adjustedBankBalance = statementClosingBalance + depositsInTransit - outstandingChecks;
    const adjustedBookBalance = statementClosingBalance + unmatchedBankInflows - unmatchedBankOutflows;
    const difference = adjustedBankBalance - adjustedBookBalance;

    const totalBankTransactions = bankTransactions.length;
    const matchedBankTransactions = matchedBankIds.size;
    const unmatchedBankTransactions = totalBankTransactions - matchedBankTransactions;
    const totalLedgerTransactions = ledgerTransactions.length;
    const unmatchedLedgerTransactions = totalLedgerTransactions - matchedLedgerCount;
    const matchRate = totalBankTransactions > 0
      ? Math.round((matchedBankTransactions / totalBankTransactions) * 100)
      : 0;

    const summary: ReconciliationSummary = {
      periodId,
      statementOpeningBalance,
      statementClosingBalance,
      totalBankInflows,
      totalBankOutflows,
      clearedBankInflows,
      clearedBankOutflows,
      unmatchedBankInflows,
      unmatchedBankOutflows,
      depositsInTransit,
      outstandingChecks,
      adjustedBankBalance,
      adjustedBookBalance,
      difference,
      totalBankTransactions,
      matchedBankTransactions,
      unmatchedBankTransactions,
      totalLedgerTransactions,
      matchedLedgerTransactions: matchedLedgerCount,
      unmatchedLedgerTransactions,
      matchRate,
    };

    return NextResponse.json(summary, { status: 200 });
  } catch (error) {
    console.error('Error computing reconciliation summary:', error);
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Internal Server Error' },
      { status: 500 }
    );
  }
}
