import { getTranslations, getCurrentLocale } from "@/lib/i18n";

import { pgGetInventoryMovements, pgGetInvoices, pgGetMaterials, pgGetPurchaseOrders, pgGetPurchaseReturns, pgGetSettings, pgGetWarehouses } from "@/lib/postgres/data-access";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import type { MaterialExpiryFifoRow, ProductionItem, Warehouse } from "@/lib/types";

type PageProps = {
  searchParams?: Promise<{
    nearDays?: string;
  }>;
};

function normalizeShelfLifePart(value: unknown): number {
  const parsed = Number(value || 0);
  return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 0;
}

function buildExpiryDate(baseDate: Date, years: number, months: number, days: number): Date {
  const next = new Date(baseDate);
  if (years > 0) next.setFullYear(next.getFullYear() + years);
  if (months > 0) next.setMonth(next.getMonth() + months);
  if (days > 0) next.setDate(next.getDate() + days);
  return next;
}

export default async function PurchaseExpiryPage({ searchParams }: PageProps) {
  const locale = await getCurrentLocale();
  const t = getTranslations(locale);
  const tPurchases = t.Purchases ?? {};
  const resolvedSearchParams = (await searchParams) || {};
  const legacyData = null;
  const settings = await pgGetSettings();
  const warehousesEnabled = settings.warehousesEnabled === true || settings.warehousesEnabled === 'true';

  const rawNearDays = Number(resolvedSearchParams.nearDays ?? 30);
  const nearDays = Number.isFinite(rawNearDays) ? Math.max(0, Math.floor(rawNearDays)) : 30;

  let rows: MaterialExpiryFifoRow[] = [];

  
  const [materialsResult, purchaseOrdersResult, purchaseReturnsResult, invoicesResult, warehousesResult, movementsResult] = await Promise.all([
  pgGetMaterials({ page: 1, pageSize: 5000 }),
  pgGetPurchaseOrders({ page: 1, pageSize: 5000 }),
  pgGetPurchaseReturns({ page: 1, pageSize: 5000 }),
  pgGetInvoices({ page: 1, pageSize: 5000 }),
  pgGetWarehouses({ page: 1, pageSize: 5000 }),
  pgGetInventoryMovements({ page: 1, pageSize: 10000 }),
  ]);

  const materials = (materialsResult.items || []) as ProductionItem[];
  const purchaseOrders = ((purchaseOrdersResult.items || []) as Array<Record<string, any>>).filter((order) => order.status !== 'cancelled');
  const purchaseReturns = ((purchaseReturnsResult.items || []) as Array<Record<string, any>>).filter((ret) => ret.status !== 'draft');
  const salesInvoices = ((invoicesResult.items || []) as Array<Record<string, any>>).filter(
  (invoice) => invoice.status !== 'cancelled' && (invoice.type || 'sale') !== 'return'
  );
  const warehouses = (warehousesResult.items || []) as Warehouse[];
  const inventoryMovements = ((movementsResult.items || []) as Array<Record<string, unknown>>);

  const materialById = new Map(materials.map((material) => [material.id, material]));
  const thresholdDays = Number.isFinite(Number(nearDays)) ? Math.max(0, Math.floor(Number(nearDays))) : 30;

  const warehouseNameById = new Map(warehouses.map((warehouse) => [warehouse.id, warehouse.name]));
  const shelfNameByCompositeId = new Map<string, string>();
  warehouses.forEach((warehouse) => {
  (warehouse.shelves || []).forEach((shelf) => {
    shelfNameByCompositeId.set(`${warehouse.id}||${shelf.id}`, shelf.name);
  });
  });

  const stockBalances = inventoryMovements.reduce<Map<string, number>>((acc, movement) => {
  const materialId = String(movement.materialId || '').trim();
  const warehouseId = String(movement.warehouseId || '').trim();
  const shelfId = String(movement.shelfId || '').trim();
  const quantity = Number(movement.quantityIn || 0) - Number(movement.quantityOut || 0);

  if (!materialId || !warehouseId || !shelfId || !Number.isFinite(quantity) || quantity === 0) {
    return acc;
  }

  const key = `${materialId}||${warehouseId}||${shelfId}`;
  acc.set(key, (acc.get(key) || 0) + quantity);
  return acc;
  }, new Map<string, number>());

  const locationSummaryParts = new Map<string, string[]>();
  Array.from(stockBalances.entries()).forEach(([key, quantity]) => {
  if (quantity <= 0) return;
  const [materialId, warehouseId, shelfId] = key.split('||');
  if (!materialId || !warehouseId || !shelfId) return;

  const list = locationSummaryParts.get(materialId) || [];
  list.push(
    `${warehouseNameById.get(warehouseId) || warehouseId} / ${shelfNameByCompositeId.get(`${warehouseId}||${shelfId}`) || shelfId} (${Math.round(quantity * 10000) / 10000})`
  );
  locationSummaryParts.set(materialId, list);
  });

  const locationSummaryByMaterial = new Map<string, string>();
  locationSummaryParts.forEach((parts, materialId) => {
  if (parts.length > 0) {
    locationSummaryByMaterial.set(materialId, parts.join('، '));
  }
  });

  const lotsByMaterial = new Map<string, Array<{
  materialId: string;
  materialName: string;
  purchaseOrderId: string;
  purchaseOrderNumber: string;
  purchaseDate: string;
  remainingQuantity: number;
  shelfLifeYears: number;
  shelfLifeMonths: number;
  shelfLifeDays: number;
  }>>();

  purchaseOrders.forEach((order) => {
  const orderItems = Array.isArray(order.items) ? order.items : [];
  orderItems.forEach((item: any) => {
    const materialId = String(item.materialId || '').trim();
    if (!materialId) return;

    const material = materialById.get(materialId);
    if (!material) return;

    const years = normalizeShelfLifePart((material as any).shelfLifeYears);
    const months = normalizeShelfLifePart((material as any).shelfLifeMonths);
    const days = normalizeShelfLifePart((material as any).shelfLifeDays);
    if (years + months + days <= 0) return;

    const quantity = Number(item.quantity || 0);
    if (!Number.isFinite(quantity) || quantity <= 0) return;

    const list = lotsByMaterial.get(materialId) || [];
    list.push({
      materialId,
      materialName: material.name,
      purchaseOrderId: String(order.id || ''),
      purchaseOrderNumber: String(order.orderNumber || order.id || ''),
      purchaseDate: String(order.date || ''),
      remainingQuantity: quantity,
      shelfLifeYears: years,
      shelfLifeMonths: months,
      shelfLifeDays: days,
    });
    lotsByMaterial.set(materialId, list);
  });
  });

  lotsByMaterial.forEach((lots) => {
  lots.sort((a, b) => {
    const dateDiff = new Date(a.purchaseDate).getTime() - new Date(b.purchaseDate).getTime();
    if (dateDiff !== 0) return dateDiff;
    return a.purchaseOrderNumber.localeCompare(b.purchaseOrderNumber);
  });
  });

  const outgoingByMaterial = new Map<string, number>();
  const addOutgoing = (materialId: string, quantity: number) => {
  if (!materialId || !Number.isFinite(quantity) || quantity <= 0) return;
  outgoingByMaterial.set(materialId, (outgoingByMaterial.get(materialId) || 0) + quantity);
  };

  salesInvoices.forEach((invoice) => {
  const invoiceItems = Array.isArray(invoice.items) ? invoice.items : [];
  invoiceItems.forEach((item: any) => addOutgoing(String(item.materialId || '').trim(), Number(item.quantity || 0)));
  });

  purchaseReturns.forEach((ret) => {
  const returnItems = Array.isArray(ret.items) ? ret.items : [];
  returnItems.forEach((item: any) => addOutgoing(String(item.materialId || '').trim(), Number(item.quantity || 0)));
  });

  outgoingByMaterial.forEach((outgoingQty, materialId) => {
  const lots = lotsByMaterial.get(materialId);
  if (!lots || lots.length === 0) return;

  let remainingToConsume = outgoingQty;
  for (const lot of lots) {
    if (remainingToConsume <= 0) break;
    if (lot.remainingQuantity <= 0) continue;
    const consumed = Math.min(lot.remainingQuantity, remainingToConsume);
    lot.remainingQuantity -= consumed;
    remainingToConsume -= consumed;
  }
  });

  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const msPerDay = 24 * 60 * 60 * 1000;

  rows = [];
  lotsByMaterial.forEach((lots) => {
  lots.forEach((lot) => {
    const remainingQuantity = Number(lot.remainingQuantity || 0);
    if (!Number.isFinite(remainingQuantity) || remainingQuantity <= 0) return;

    const purchaseDate = new Date(lot.purchaseDate);
    if (Number.isNaN(purchaseDate.getTime())) return;

    const expiryDate = buildExpiryDate(purchaseDate, lot.shelfLifeYears, lot.shelfLifeMonths, lot.shelfLifeDays);
    const expiryStart = new Date(expiryDate);
    expiryStart.setHours(0, 0, 0, 0);
    const remainingDays = Math.floor((expiryStart.getTime() - today.getTime()) / msPerDay);

    const status: MaterialExpiryFifoRow['status'] = remainingDays < 0 ? 'expired' : remainingDays <= thresholdDays ? 'near-expiry' : 'valid';
    if (status === 'valid') return;

    rows.push({
      materialId: lot.materialId,
      materialName: lot.materialName,
      locationSummary: locationSummaryByMaterial.get(lot.materialId),
      purchaseOrderId: lot.purchaseOrderId,
      purchaseOrderNumber: lot.purchaseOrderNumber,
      purchaseDate: lot.purchaseDate,
      expiryDate: expiryDate.toISOString(),
      shelfLifeDays: lot.shelfLifeYears * 365 + lot.shelfLifeMonths * 30 + lot.shelfLifeDays,
      remainingQuantity: Math.round(remainingQuantity * 10000) / 10000,
      remainingDays,
      status,
    });
  });
  });

  rows.sort((a, b) => {
  const rank = (value: MaterialExpiryFifoRow['status']) => (value === 'expired' ? 0 : value === 'near-expiry' ? 1 : 2);
  const rankDiff = rank(a.status) - rank(b.status);
  if (rankDiff !== 0) return rankDiff;
  const daysDiff = a.remainingDays - b.remainingDays;
  if (daysDiff !== 0) return daysDiff;
  return a.materialName.localeCompare(b.materialName);
  });
  

  const expiredCount = rows.filter((row) => row.status === 'expired').length;
  const nearCount = rows.filter((row) => row.status === 'near-expiry').length;
  const totalRemaining = rows.reduce((sum, row) => sum + Number(row.remainingQuantity || 0), 0);

  const statusBadge = (status: 'expired' | 'near-expiry' | 'valid') => {
    if (status === 'expired') {
      return <Badge variant="destructive">{tPurchases.expiryStatusExpired ?? 'منتهي'}</Badge>;
    }
    if (status === 'near-expiry') {
      return <Badge variant="secondary">{tPurchases.expiryStatusNear ?? 'قارب الانتهاء'}</Badge>;
    }
    return <Badge variant="outline">{tPurchases.expiryStatusValid ?? 'سليم'}</Badge>;
  };

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <CardTitle>{tPurchases.expiryReportTitle ?? 'تقرير فحص صلاحية الأصناف (FIFO)'}</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <form method="GET" className="flex flex-wrap items-end gap-3">
            <div className="space-y-1">
              <label htmlFor="nearDays" className="text-sm font-medium">
                {tPurchases.nearExpiryDaysLabel ?? 'عدد الأيام قبل الانتهاء'}
              </label>
              <Input id="nearDays" name="nearDays" type="number" min={0} step={1} defaultValue={nearDays} className="w-40" />
            </div>
            <Button type="submit">{tPurchases.applyFilterButton ?? 'تطبيق'}</Button>
          </form>

          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <div className="space-y-2 rounded-md border p-4">
              <div className="text-sm text-muted-foreground">{tPurchases.expiredItemsCount ?? 'عدد البنود المنتهية'}</div>
              <div className="text-2xl font-bold text-destructive">{expiredCount}</div>
            </div>
            <div className="space-y-2 rounded-md border p-4">
              <div className="text-sm text-muted-foreground">{tPurchases.nearExpiryItemsCount ?? 'عدد البنود القريبة من الانتهاء'}</div>
              <div className="text-2xl font-bold">{nearCount}</div>
            </div>
            <div className="space-y-2 rounded-md border p-4">
              <div className="text-sm text-muted-foreground">{tPurchases.expiryRemainingQty ?? 'إجمالي الكمية المتبقية'}</div>
              <div className="text-2xl font-bold">{Math.round(totalRemaining * 10000) / 10000}</div>
            </div>
          </div>

          <div className="rounded-md border">
            <div className="relative w-full overflow-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{tPurchases.itemName ?? 'الصنف'}</TableHead>
                    {warehousesEnabled && <TableHead>{tPurchases.locationLabel ?? 'الموقع'}</TableHead>}
                    <TableHead>{tPurchases.orderNumber ?? 'رقم أمر الشراء'}</TableHead>
                    <TableHead>{tPurchases.date ?? 'تاريخ الشراء'}</TableHead>
                    <TableHead>{tPurchases.expiryDate ?? 'تاريخ الانتهاء'}</TableHead>
                    <TableHead className="text-right">{tPurchases.remainingQuantity ?? 'الكمية المتبقية'}</TableHead>
                    <TableHead className="text-right">{tPurchases.remainingDays ?? 'الأيام المتبقية'}</TableHead>
                    <TableHead>{tPurchases.status ?? 'الحالة'}</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {rows.length === 0 ? (
                    <TableRow>
                      <TableCell colSpan={warehousesEnabled ? 8 : 7} className="text-center text-muted-foreground py-8">
                        {tPurchases.noExpiryRows ?? 'لا توجد أصناف منتهية أو قريبة من الانتهاء حسب النطاق المحدد.'}
                      </TableCell>
                    </TableRow>
                  ) : (
                    rows.map((row) => (
                      <TableRow key={`${row.materialId}-${row.purchaseOrderId}-${row.expiryDate}`}>
                        <TableCell className="font-medium">{row.materialName}</TableCell>
                        {warehousesEnabled && <TableCell>{row.locationSummary || (tPurchases.locationUnknown ?? 'غير محدد')}</TableCell>}
                        <TableCell>{row.purchaseOrderNumber}</TableCell>
                        <TableCell>{format(new Date(row.purchaseDate), 'yyyy-MM-dd')}</TableCell>
                        <TableCell>{format(new Date(row.expiryDate), 'yyyy-MM-dd')}</TableCell>
                        <TableCell className="text-right">{row.remainingQuantity}</TableCell>
                        <TableCell className={`text-right ${row.remainingDays < 0 ? 'text-destructive font-semibold' : ''}`}>{row.remainingDays}</TableCell>
                        <TableCell>{statusBadge(row.status)}</TableCell>
                      </TableRow>
                    ))
                  )}
                </TableBody>
              </Table>
            </div>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}
