import { redirect } from 'next/navigation';
import { getSession } from '@/lib/auth';
import { pgGetCustomers, pgGetInvoices, pgGetPayments } from '@/lib/postgres/data-access';
import { formatDateDDMMYYYY } from '@/lib/utils';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { formatCurrency } from '@/lib/currency-formatter';
import { getCurrencySymbolAsync } from '@/lib/server-currency';

export const metadata = { title: 'Coverage Receivables Report | Sales' };

type CoverageKind = 'primary' | 'secondary';

type CoverageRow = {
  invoiceId: string;
  invoiceNumber: string;
  invoiceDate: string;
  invoiceStatus: string;
  coverageKind: CoverageKind;
  customerId: string;
  customerName: string;
  coveragePercent: number;
  invoiceAmountTx: number;
  invoiceAmountBase: number;
  paidAmountTx: number;
  paidAmountBase: number;
  remainingAmountTx: number;
  remainingAmountBase: number;
  currencyCode: string;
  baseCurrencyCode: string;
  exchangeRate: number;
  paymentCount: number;
};

interface CoverageReportPageProps {
  searchParams?: Promise<{
    from?: string;
    to?: string;
    customerId?: string;
    coverage?: string;
    status?: string;
  }>;
}

function round2(value: number): number {
  return Math.round((Number(value || 0) + Number.EPSILON) * 100) / 100;
}

function normalizeDateOnly(value?: string): string {
  const source = String(value || '').trim();
  if (!source) return '';
  const parsed = new Date(source);
  if (Number.isNaN(parsed.getTime())) return '';
  return parsed.toISOString().slice(0, 10);
}

function safeDate(value?: string): Date {
  const parsed = new Date(String(value || ''));
  if (Number.isNaN(parsed.getTime())) return new Date(0);
  return parsed;
}

export default async function CoverageReportPage({ searchParams }: CoverageReportPageProps) {
  const session = await getSession();
  if (!session?.user) {
    redirect('/login');
  }

  const resolvedSearchParams = (await searchParams) || {};
  const from = normalizeDateOnly(resolvedSearchParams.from);
  const to = normalizeDateOnly(resolvedSearchParams.to);
  const customerIdFilter = String(resolvedSearchParams.customerId || '').trim();
  const coverageFilter = String(resolvedSearchParams.coverage || 'all').trim();
  const statusFilter = String(resolvedSearchParams.status || 'all').trim();

  const [customersResult, invoicesResult, paymentsResult, currencySymbol] = await Promise.all([
    pgGetCustomers({ page: 1, pageSize: 5000 }),
    pgGetInvoices({ page: 1, pageSize: 5000 }),
    pgGetPayments({ page: 1, pageSize: 5000 }),
    getCurrencySymbolAsync(),
  ]);

  const customers = customersResult.items || [];
  const customerNameById = new Map(
    customers.map((customer: any) => [String(customer.id || '').trim(), String(customer.name || '').trim()])
  );

  const allInvoices = (invoicesResult.items || []).filter((invoice: any) => {
    const status = String(invoice.status || 'active').trim().toLowerCase();
    const docType = String(invoice.documentType || 'tax_invoice').trim().toLowerCase();
    const secondaryCustomerId = String(invoice.secondaryCustomerId || '').trim();
    const secondaryPercent = Math.max(0, Math.min(100, Number(invoice.secondaryCoveragePercent || 0)));
    if (status === 'cancelled') return false;
    if (docType === 'shipment') return false;
    // This report is only for invoices that are split between primary and secondary liabilities.
    return Boolean(secondaryCustomerId) && secondaryPercent > 0 && secondaryPercent < 100;
  });

  const filteredInvoices = allInvoices.filter((invoice: any) => {
    const invoiceDate = normalizeDateOnly(String(invoice.date || ''));
    if (from && invoiceDate && invoiceDate < from) return false;
    if (to && invoiceDate && invoiceDate > to) return false;
    return true;
  });

  const activePayments = (paymentsResult.items || []).filter((payment: any) => {
    const status = String(payment.status || 'active').trim().toLowerCase();
    return status !== 'cancelled';
  });

  const allocationMap = new Map<string, Array<any>>();
  for (const payment of activePayments) {
    const paymentCustomerId = String(payment.customerId || '').trim();
    const allocations = Array.isArray(payment.allocations) ? payment.allocations : [];
    for (const allocation of allocations) {
      const invoiceId = String(allocation?.invoiceId || '').trim();
      if (!invoiceId) continue;
      const key = `${invoiceId}::${paymentCustomerId}`;
      const current = allocationMap.get(key) || [];
      current.push({ payment, allocation });
      allocationMap.set(key, current);
    }
  }

  const rows: CoverageRow[] = [];

  for (const invoice of filteredInvoices) {
    const invoiceId = String(invoice.id || '').trim();
    if (!invoiceId) continue;

    const invoiceNumber = String(invoice.invoiceNumber || invoiceId);
    const invoiceDate = String(invoice.date || '');
    const invoiceStatus = String(invoice.paymentStatus || 'due');
    const invoiceCurrencyCode = String(invoice.currencyCode || invoice.baseCurrencyCode || '').trim() || 'N/A';
    const baseCurrencyCode = String(invoice.baseCurrencyCode || invoice.currencyCode || '').trim() || invoiceCurrencyCode;
    const exchangeRate = Number(invoice.exchangeRate || 1) || 1;

    const totalTx = round2(Number(invoice.grandTotal || 0));
    const totalBase = round2(
      Number.isFinite(Number(invoice.grandTotalBase)) && Number(invoice.grandTotalBase) > 0
        ? Number(invoice.grandTotalBase)
        : totalTx * exchangeRate
    );

    const primaryCustomerId = String(invoice.customerId || '').trim();
    const primaryCustomerName = String(invoice.customerName || customerNameById.get(primaryCustomerId) || primaryCustomerId || '-').trim();

    const secondaryCustomerId = String(invoice.secondaryCustomerId || '').trim();
    const secondaryCustomerName = String(invoice.secondaryCustomerName || customerNameById.get(secondaryCustomerId) || secondaryCustomerId || '-').trim();
    const secondaryPercent = secondaryCustomerId
      ? Math.max(0, Math.min(100, Number(invoice.secondaryCoveragePercent || 0)))
      : 0;
    const primaryPercent = Math.max(0, round2(100 - secondaryPercent));

    const secondaryAmountTx = secondaryCustomerId
      ? round2(
          Number.isFinite(Number(invoice.secondaryCoverageAmount)) && Number(invoice.secondaryCoverageAmount) > 0
            ? Number(invoice.secondaryCoverageAmount)
            : (totalTx * secondaryPercent) / 100
        )
      : 0;
    const primaryAmountTx = round2(Math.max(0, totalTx - secondaryAmountTx));

    const primaryAmountBase = totalTx > 0 ? round2((primaryAmountTx / totalTx) * totalBase) : 0;
    const secondaryAmountBase = totalTx > 0 ? round2((secondaryAmountTx / totalTx) * totalBase) : 0;

    const addCoverageRow = (params: {
      coverageKind: CoverageKind;
      customerId: string;
      customerName: string;
      coveragePercent: number;
      amountTx: number;
      amountBase: number;
    }) => {
      if (!params.customerId || params.amountTx <= 0) return;

      const allocationsForLiability = allocationMap.get(`${invoiceId}::${params.customerId}`) || [];
      let paidBase = 0;
      let paidTx = 0;

      for (const entry of allocationsForLiability) {
        const allocation = entry.allocation;
        const allocAmount = Number(allocation?.amount || 0);
        const allocAmountBase = Number(allocation?.amountBase || 0);
        const allocInvoiceRate = Number(allocation?.invoiceExchangeRate || exchangeRate) || exchangeRate;

        const effectiveBase = Number.isFinite(allocAmountBase) && allocAmountBase > 0
          ? allocAmountBase
          : allocAmount * allocInvoiceRate;
        paidBase += effectiveBase;

        const allocCurrency = String(allocation?.invoiceCurrencyCode || invoiceCurrencyCode).trim();
        if (allocCurrency === invoiceCurrencyCode) {
          paidTx += allocAmount;
        } else {
          paidTx += allocInvoiceRate > 0 ? effectiveBase / allocInvoiceRate : allocAmount;
        }
      }

      paidBase = round2(paidBase);
      paidTx = round2(paidTx);

      const remainingTx = round2(Math.max(0, params.amountTx - paidTx));
      const remainingBase = round2(Math.max(0, params.amountBase - paidBase));

      rows.push({
        invoiceId,
        invoiceNumber,
        invoiceDate,
        invoiceStatus,
        coverageKind: params.coverageKind,
        customerId: params.customerId,
        customerName: params.customerName || params.customerId,
        coveragePercent: round2(params.coveragePercent),
        invoiceAmountTx: round2(params.amountTx),
        invoiceAmountBase: round2(params.amountBase),
        paidAmountTx: paidTx,
        paidAmountBase: paidBase,
        remainingAmountTx: remainingTx,
        remainingAmountBase: remainingBase,
        currencyCode: invoiceCurrencyCode,
        baseCurrencyCode,
        exchangeRate,
        paymentCount: allocationsForLiability.length,
      });
    };

    addCoverageRow({
      coverageKind: 'primary',
      customerId: primaryCustomerId,
      customerName: primaryCustomerName,
      coveragePercent: primaryPercent,
      amountTx: primaryAmountTx,
      amountBase: primaryAmountBase,
    });

    if (secondaryCustomerId && secondaryPercent > 0) {
      addCoverageRow({
        coverageKind: 'secondary',
        customerId: secondaryCustomerId,
        customerName: secondaryCustomerName,
        coveragePercent: secondaryPercent,
        amountTx: secondaryAmountTx,
        amountBase: secondaryAmountBase,
      });
    }
  }

  const filteredRows = rows
    .filter((row) => {
      if (customerIdFilter && row.customerId !== customerIdFilter) return false;
      if (coverageFilter === 'primary' && row.coverageKind !== 'primary') return false;
      if (coverageFilter === 'secondary' && row.coverageKind !== 'secondary') return false;

      if (statusFilter === 'open' && row.remainingAmountBase <= 0) return false;
      if (statusFilter === 'paid' && row.remainingAmountBase > 0) return false;
      return true;
    })
    .sort((a, b) => {
      const byDate = safeDate(b.invoiceDate).getTime() - safeDate(a.invoiceDate).getTime();
      if (byDate !== 0) return byDate;
      return a.invoiceNumber.localeCompare(b.invoiceNumber);
    });

  const totals = filteredRows.reduce(
    (acc, row) => {
      acc.invoiceBase += row.invoiceAmountBase;
      acc.paidBase += row.paidAmountBase;
      acc.remainingBase += row.remainingAmountBase;

      if (row.coverageKind === 'primary') {
        acc.primaryInvoiceBase += row.invoiceAmountBase;
        acc.primaryPaidBase += row.paidAmountBase;
        acc.primaryRemainingBase += row.remainingAmountBase;
      } else {
        acc.secondaryInvoiceBase += row.invoiceAmountBase;
        acc.secondaryPaidBase += row.paidAmountBase;
        acc.secondaryRemainingBase += row.remainingAmountBase;
      }
      return acc;
    },
    {
      invoiceBase: 0,
      paidBase: 0,
      remainingBase: 0,
      primaryInvoiceBase: 0,
      primaryPaidBase: 0,
      primaryRemainingBase: 0,
      secondaryInvoiceBase: 0,
      secondaryPaidBase: 0,
      secondaryRemainingBase: 0,
    }
  );

  const fmt = (amount: number) => formatCurrency(amount, currencySymbol);

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-3xl font-bold">تقرير ذمم التغطية</h1>
        <p className="text-muted-foreground mt-1">
          كشف منفصل يوضح ذمة العميل الرئيسي والثانوي ونسبة التغطية والدفعات لكل ذمة.
        </p>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>فلاتر التقرير</CardTitle>
        </CardHeader>
        <CardContent>
          <form className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-3" method="get">
            <div className="space-y-1">
              <label className="text-xs text-muted-foreground">من تاريخ</label>
              <Input type="date" name="from" defaultValue={from} />
            </div>
            <div className="space-y-1">
              <label className="text-xs text-muted-foreground">إلى تاريخ</label>
              <Input type="date" name="to" defaultValue={to} />
            </div>
            <div className="space-y-1">
              <label className="text-xs text-muted-foreground">العميل</label>
              <select
                name="customerId"
                defaultValue={customerIdFilter}
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              >
                <option value="">كل العملاء</option>
                {customers.map((customer: any) => (
                  <option key={String(customer.id)} value={String(customer.id)}>
                    {String(customer.name || customer.id)}
                  </option>
                ))}
              </select>
            </div>
            <div className="space-y-1">
              <label className="text-xs text-muted-foreground">نوع الذمة</label>
              <select
                name="coverage"
                defaultValue={coverageFilter || 'all'}
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              >
                <option value="all">الكل</option>
                <option value="primary">رئيسية</option>
                <option value="secondary">ثانوية</option>
              </select>
            </div>
            <div className="space-y-1">
              <label className="text-xs text-muted-foreground">حالة السداد</label>
              <select
                name="status"
                defaultValue={statusFilter || 'all'}
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              >
                <option value="all">الكل</option>
                <option value="open">مفتوحة/جزئية</option>
                <option value="paid">مسددة</option>
              </select>
            </div>
            <div className="flex items-end gap-2">
              <Button type="submit" className="w-full">تطبيق</Button>
            </div>
          </form>
        </CardContent>
      </Card>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        <Card>
          <CardContent className="pt-6">
            <p className="text-sm text-muted-foreground">إجمالي الذمم (عملة الأساس)</p>
            <p className="text-2xl font-bold">{fmt(totals.invoiceBase)}</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <p className="text-sm text-muted-foreground">إجمالي المدفوع (عملة الأساس)</p>
            <p className="text-2xl font-bold text-emerald-700">{fmt(totals.paidBase)}</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <p className="text-sm text-muted-foreground">إجمالي المتبقي (عملة الأساس)</p>
            <p className="text-2xl font-bold text-rose-700">{fmt(totals.remainingBase)}</p>
          </CardContent>
        </Card>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        <Card>
          <CardHeader>
            <CardTitle>ملخص الذمة الرئيسية</CardTitle>
          </CardHeader>
          <CardContent className="space-y-1 text-sm">
            <div className="flex items-center justify-between"><span>إجمالي الذمم</span><span className="font-semibold">{fmt(totals.primaryInvoiceBase)}</span></div>
            <div className="flex items-center justify-between"><span>المدفوع</span><span className="font-semibold text-emerald-700">{fmt(totals.primaryPaidBase)}</span></div>
            <div className="flex items-center justify-between"><span>المتبقي</span><span className="font-semibold text-rose-700">{fmt(totals.primaryRemainingBase)}</span></div>
          </CardContent>
        </Card>
        <Card>
          <CardHeader>
            <CardTitle>ملخص الذمة الثانوية</CardTitle>
          </CardHeader>
          <CardContent className="space-y-1 text-sm">
            <div className="flex items-center justify-between"><span>إجمالي الذمم</span><span className="font-semibold">{fmt(totals.secondaryInvoiceBase)}</span></div>
            <div className="flex items-center justify-between"><span>المدفوع</span><span className="font-semibold text-emerald-700">{fmt(totals.secondaryPaidBase)}</span></div>
            <div className="flex items-center justify-between"><span>المتبقي</span><span className="font-semibold text-rose-700">{fmt(totals.secondaryRemainingBase)}</span></div>
          </CardContent>
        </Card>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>تفاصيل الذمم حسب الفاتورة</CardTitle>
        </CardHeader>
        <CardContent>
          <div className="rounded-md border overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>الفاتورة</TableHead>
                  <TableHead>التاريخ</TableHead>
                  <TableHead>نوع الذمة</TableHead>
                  <TableHead>العميل</TableHead>
                  <TableHead>نسبة التغطية</TableHead>
                  <TableHead>قيمة الذمة</TableHead>
                  <TableHead>المدفوع</TableHead>
                  <TableHead>المتبقي</TableHead>
                  <TableHead>العملة/الصرف</TableHead>
                  <TableHead>عدد الدفعات</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {filteredRows.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={10} className="text-center text-muted-foreground py-8">
                      لا توجد بيانات مطابقة للفلاتر.
                    </TableCell>
                  </TableRow>
                ) : (
                  filteredRows.map((row) => (
                    <TableRow key={`${row.invoiceId}:${row.coverageKind}:${row.customerId}`}>
                      <TableCell className="font-medium">{row.invoiceNumber}</TableCell>
                      <TableCell>{formatDateDDMMYYYY(row.invoiceDate)}</TableCell>
                      <TableCell>{row.coverageKind === 'primary' ? 'رئيسية' : 'ثانوية'}</TableCell>
                      <TableCell>{row.customerName}</TableCell>
                      <TableCell>{row.coveragePercent.toFixed(2)}%</TableCell>
                      <TableCell>
                        <div className="text-sm" lang="en" dir="ltr">{row.invoiceAmountTx.toFixed(2)} {row.currencyCode}</div>
                        <div className="text-xs text-muted-foreground">{fmt(row.invoiceAmountBase)}</div>
                      </TableCell>
                      <TableCell>
                        <div className="text-sm text-emerald-700" lang="en" dir="ltr">{row.paidAmountTx.toFixed(2)} {row.currencyCode}</div>
                        <div className="text-xs text-muted-foreground">{fmt(row.paidAmountBase)}</div>
                      </TableCell>
                      <TableCell>
                        <div className={`text-sm font-semibold ${row.remainingAmountBase > 0 ? 'text-rose-700' : 'text-emerald-700'}`} lang="en" dir="ltr">
                          {row.remainingAmountTx.toFixed(2)} {row.currencyCode}
                        </div>
                        <div className="text-xs text-muted-foreground">{fmt(row.remainingAmountBase)}</div>
                      </TableCell>
                      <TableCell>
                        <div className="text-sm" lang="en" dir="ltr">{row.currencyCode} / {row.baseCurrencyCode}</div>
                        <div className="text-xs text-muted-foreground" lang="en" dir="ltr">{row.exchangeRate.toFixed(4)}</div>
                      </TableCell>
                      <TableCell>{row.paymentCount}</TableCell>
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}
