import { verifySession } from '@/lib/auth';

import { getCurrentLocale, getTranslations } from '@/lib/i18n';
import { Card, CardHeader, CardTitle } from '@/components/ui/card';
import { getCurrencySymbolAsync } from '@/lib/server-currency';
import BalancesReportClient from '@/components/admin/reports/balances-report-client';

type BalanceRow = {
  id: string;
  name: string;
  type: 'customer' | 'supplier';
  accountCode?: string;
  balancePostedOnly: number;
  balanceAllEntries: number;
  searchText: string;
};

function buildSearchTextFromRecord(record: unknown): string {
  const values: string[] = [];

  const visit = (node: unknown): void => {
    if (node === null || node === undefined) return;
    if (Array.isArray(node)) {
      node.forEach(visit);
      return;
    }
    if (typeof node === 'object') {
      Object.values(node as Record<string, unknown>).forEach(visit);
      return;
    }
    if (typeof node === 'string' || typeof node === 'number' || typeof node === 'boolean') {
      const value = String(node).trim();
      if (value) values.push(value);
    }
  };

  visit(record);
  return values.join(' ');
}

export default async function ReportsBalancesPage() {
  const session = await verifySession();
  const user = session.user;
  const locale = await getCurrentLocale();
  const t = getTranslations(locale);
  const tGlobal = t.Global ?? {};

  if (!user || user.role !== 'admin') {
    return (
      <div className="text-center">
        <h1 className="text-2xl font-bold">{tGlobal.accessDenied ?? 'Access Denied'}</h1>
        <p>{tGlobal.noPermission ?? 'You do not have permission to view this page.'}</p>
      </div>
    );
  }

  let customers = [];
  let suppliers = [];
  let journalEntries = [];

  
  const { pgGetCustomers, pgGetSuppliers, pgGetJournalEntries } = await import('@/lib/postgres/data-access');

  const [customersResult, suppliersResult, journalEntriesResult] = await Promise.all([
  pgGetCustomers({ page: 1, pageSize: 5000 }),
  pgGetSuppliers({ page: 1, pageSize: 5000 }),
  pgGetJournalEntries({ page: 1, pageSize: 10000 }),
  ]);

  customers = (customersResult.items || []) as typeof customers;
  suppliers = (suppliersResult.items || []) as typeof suppliers;
  journalEntries = (journalEntriesResult.items || []) as typeof journalEntries;

  const customerById = new Map(customers.map((customer: any) => [String(customer.id || '').trim(), customer]));
  const supplierById = new Map(suppliers.map((supplier: any) => [String(supplier.id || '').trim(), supplier]));

  const customerByCode = new Map(
    customers
      .map((customer: any) => ({ id: String(customer.id || '').trim(), code: String(customer.accountCode || '').trim() }))
      .filter((entry) => entry.id && entry.code)
      .map((entry) => [entry.code, entry.id])
  );
  const supplierByCode = new Map(
    suppliers
      .map((supplier: any) => ({ id: String(supplier.id || '').trim(), code: String(supplier.accountCode || '').trim() }))
      .filter((entry) => entry.id && entry.code)
      .map((entry) => [entry.code, entry.id])
  );

  const customerByAccountId = new Map(
    customers
      .map((customer: any) => ({ id: String(customer.id || '').trim(), accountId: String(customer.accountId || '').trim() }))
      .filter((entry) => entry.id && entry.accountId)
      .map((entry) => [entry.accountId, entry.id])
  );
  const supplierByAccountId = new Map(
    suppliers
      .map((supplier: any) => ({ id: String(supplier.id || '').trim(), accountId: String(supplier.accountId || '').trim() }))
      .filter((entry) => entry.id && entry.accountId)
      .map((entry) => [entry.accountId, entry.id])
  );

  const customerBalancePostedOnlyById = new Map<string, number>();
  const supplierBalancePostedOnlyById = new Map<string, number>();
  const customerBalanceAllEntriesById = new Map<string, number>();
  const supplierBalanceAllEntriesById = new Map<string, number>();

  (journalEntries || [])
    .forEach((entry: any) => {
      const entryStatus = String(entry?.status || 'posted').trim().toLowerCase();
      const includeInPostedOnly = entryStatus !== 'draft';
      const lines = Array.isArray(entry?.lines) ? entry.lines : [];
      lines.forEach((line: any) => {
        const accountCode = String(line?.accountCode || '').trim();
        const accountId = String(line?.accountId || '').trim();
        const debit = Number(line?.debit || 0);
        const credit = Number(line?.credit || 0);
        if (!Number.isFinite(debit) || !Number.isFinite(credit)) return;
        const net = debit - credit;
        if (Math.abs(net) < 1e-9) return;

        const customerId = customerByCode.get(accountCode) || customerByAccountId.get(accountId);
        if (customerId) {
          customerBalanceAllEntriesById.set(customerId, (customerBalanceAllEntriesById.get(customerId) || 0) + net);
          if (includeInPostedOnly) {
            customerBalancePostedOnlyById.set(customerId, (customerBalancePostedOnlyById.get(customerId) || 0) + net);
          }
          return;
        }

        const supplierId = supplierByCode.get(accountCode) || supplierByAccountId.get(accountId);
        if (supplierId) {
          supplierBalanceAllEntriesById.set(supplierId, (supplierBalanceAllEntriesById.get(supplierId) || 0) + net);
          if (includeInPostedOnly) {
            supplierBalancePostedOnlyById.set(supplierId, (supplierBalancePostedOnlyById.get(supplierId) || 0) + net);
          }
        }
      });
    });
  

  const rows: BalanceRow[] = [
    ...customers.map((customer: any) => ({
      id: `customer:${String(customer.id || '').trim()}`,
      name: String(customer.name || '').trim() || '-',
      type: 'customer' as const,
      accountCode: String(customer.accountCode || '').trim() || undefined,
      balancePostedOnly: Number(customerBalancePostedOnlyById.get(String(customer.id || '').trim()) || 0),
      balanceAllEntries: Number(customerBalanceAllEntriesById.get(String(customer.id || '').trim()) || 0),
      searchText: buildSearchTextFromRecord(customer),
    })),
    ...suppliers.map((supplier: any) => ({
      id: `supplier:${String(supplier.id || '').trim()}`,
      name: String(supplier.name || '').trim() || '-',
      type: 'supplier' as const,
      accountCode: String(supplier.accountCode || '').trim() || undefined,
      balancePostedOnly: Number(supplierBalancePostedOnlyById.get(String(supplier.id || '').trim()) || 0),
      balanceAllEntries: Number(supplierBalanceAllEntriesById.get(String(supplier.id || '').trim()) || 0),
      searchText: buildSearchTextFromRecord(supplier),
    })),
  ]
    .filter((row) => row.id !== 'customer:' && row.id !== 'supplier:')
    .filter((row) => Math.abs(Number(row.balancePostedOnly || 0)) > 0.0001 || Math.abs(Number(row.balanceAllEntries || 0)) > 0.0001)
    .sort((a, b) => Math.abs(b.balanceAllEntries) - Math.abs(a.balanceAllEntries));

  const currencySymbol = await getCurrencySymbolAsync();

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <CardTitle>{t.DashboardLayout?.balancesReport ?? 'ملخص الأرصدة لكل ذمة'}</CardTitle>
        </CardHeader>
        <BalancesReportClient rows={rows} currencySymbol={currencySymbol} />
      </Card>
    </div>
  );
}
