
import { verifySession } from "@/lib/auth";
import { hasEmployeePermission } from "@/lib/employee-permissions";
import {
  pgGetCustomerCategories,
  pgGetInventoryMovements,
  pgGetItemGroups,
  pgGetInternalTransfers,
  pgGetManagedUnits,
  pgGetMaterials,
  pgGetProductShapeDefinitions,
  pgGetSettings,
  pgGetWarehouses,
} from "@/lib/postgres/data-access";
import { getTranslations, getCurrentLocale } from "@/lib/i18n";
import { getCurrencySymbolAsync } from "@/lib/server-currency";
import ListManager from "@/components/admin/list-manager";
import { getChartOfAccountsWithSeedMerge } from "@/lib/accounting/chart-of-accounts-runtime";
import { handleGetRealEstateProjects } from "@/lib/actions";
import type {
  ChartOfAccount,
  CustomerCategory,
  InternalTransferDocument,
  ItemGroup,
  ManagedUnit,
  ProductionItem,
  RealEstateProject,
  StockLocationBalance,
  Warehouse,
} from "@/lib/types";

type ManageMaterialsPageProps = {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
};

export default async function ManageMaterialsPage({ searchParams }: ManageMaterialsPageProps) {
  const session = await verifySession();
  const user = session.user;
  const locale = await getCurrentLocale();
  const t = getTranslations(locale);
  const tGlobal = t.Global || {};
  const tLists = t.ItemLists || {};
  const currencySymbol = await getCurrencySymbolAsync();
  const settings = await pgGetSettings();
  const params = (await searchParams) || {};

  const search = String(params.search || '').trim();
  const materialFilters = {
    itemNumber: String(params.itemNumber || '').trim(),
    name: String(params.name || '').trim(),
    itemSymbolName: String(params.itemSymbolName || '').trim(),
    globalReferenceNumber: String(params.globalReferenceNumber || '').trim(),
    barcode: String(params.barcode || '').trim(),
    secondaryBarcode: String(params.secondaryBarcode || '').trim(),
    additionalDetails: String(params.additionalDetails || '').trim(),
    salePrice: String(params.salePrice || '').trim(),
    location: String(params.location || '').trim(),
  };
  const allowedFilterModes = new Set(['contains', 'startsWith', 'endsWith']);
  const readFilterMode = (key: string): 'contains' | 'startsWith' | 'endsWith' => {
    const rawMode = String((params as any)[`${key}Mode`] || '').trim();
    return allowedFilterModes.has(rawMode) ? (rawMode as 'contains' | 'startsWith' | 'endsWith') : 'contains';
  };
  const materialFilterModes = {
    itemNumber: readFilterMode('itemNumber'),
    name: readFilterMode('name'),
    itemSymbolName: readFilterMode('itemSymbolName'),
    globalReferenceNumber: readFilterMode('globalReferenceNumber'),
    barcode: readFilterMode('barcode'),
    secondaryBarcode: readFilterMode('secondaryBarcode'),
    additionalDetails: readFilterMode('additionalDetails'),
    salePrice: readFilterMode('salePrice'),
    location: readFilterMode('location'),
  };
  const page = Math.max(1, Number(params.page || 1) || 1);
  const pageSize = Math.min(100, Math.max(10, Number(params.pageSize || 25) || 25));
  const hasAlternativesOnly = String(params.hasAlternativesOnly || '').trim().toLowerCase() === 'true';
  const availableOnly = String(params.availableOnly || '').trim().toLowerCase() === 'true';
  const allowedSortKeys = new Set(['itemNumber', 'name', 'itemSymbolName', 'globalReferenceNumber', 'barcode', 'secondaryBarcode', 'additionalDetails', 'salePrice']);
  const rawSortKey = String(params.sortKey || '').trim();
  const sortKey = allowedSortKeys.has(rawSortKey) ? rawSortKey : '';
  const sortDir = String(params.sortDir || 'desc').trim().toLowerCase() === 'asc' ? 'asc' : 'desc';

  if (!user || !hasEmployeePermission(user, settings, 'admin.materials')) {
    return (
      <div className="text-center">
        <h1 className="text-2xl font-bold">{tGlobal?.accessDenied ?? "الوصول مرفوض"}</h1>
        <p>{tGlobal?.noPermission ?? "ليس لديك صلاحية لعرض هذه الصفحة."}</p>
      </div>
    );
  }

  const warehousesEnabled = settings.warehousesEnabled === true || settings.warehousesEnabled === 'true';
  const storeModuleEnabled = (settings as any).storeModuleEnabled === true || (settings as any).storeModuleEnabled === 'true';

  const [
    categoriesResult,
    itemGroupsResult,
    unitDefinitionsResult,
    productShapeDefinitionsResult,
    realEstateProjectsResult,
    warehousesResult,
    internalTransferDocumentsResult,
    inventoryMovementsResult,
    chartOfAccounts,
  ] = await Promise.all([
    pgGetCustomerCategories({ page: 1, pageSize: 5000 }),
    pgGetItemGroups({ page: 1, pageSize: 5000 }),
    pgGetManagedUnits({ page: 1, pageSize: 5000 }),
    pgGetProductShapeDefinitions({ page: 1, pageSize: 5000 }),
    handleGetRealEstateProjects(),
    warehousesEnabled ? pgGetWarehouses({ page: 1, pageSize: 5000 }) : Promise.resolve({ items: [] }),
    warehousesEnabled ? pgGetInternalTransfers({ page: 1, pageSize: 5000 }) : Promise.resolve({ items: [] }),
    warehousesEnabled ? pgGetInventoryMovements({ page: 1, pageSize: 10000 }) : Promise.resolve({ items: [] }),
    getChartOfAccountsWithSeedMerge(),
  ]);
  const categories = categoriesResult.items as CustomerCategory[];
  const itemGroups = itemGroupsResult.items as ItemGroup[];
  const unitDefinitions = unitDefinitionsResult.items as ManagedUnit[];
  const productShapeDefinitions = productShapeDefinitionsResult.items as Array<Record<string, unknown>>;
  const realEstateProjects: RealEstateProject[] = realEstateProjectsResult && 'success' in realEstateProjectsResult && realEstateProjectsResult.success
    ? (((realEstateProjectsResult as any).items || []) as RealEstateProject[])
    : [];
  const warehouses: Warehouse[] = warehousesResult.items as Warehouse[];
  const internalTransferDocuments: InternalTransferDocument[] = internalTransferDocumentsResult.items as InternalTransferDocument[];
  const inventoryMovements = ((inventoryMovementsResult.items || []) as Array<Record<string, unknown>>);

  let stockLocationsByMaterial: Record<string, StockLocationBalance[]> = {};
  if (warehousesEnabled) {
    
    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 transferRefTypes = new Set([
    'transfer_document',
    'transfer-doc',
    'transfer_doc',
    'internal_transfer_doc',
    'transfer_document_receipt',
    'transfer_document_nullified',
    'transfer_document_reversal',
    'transfer_document_cancel',
    ]);

    const addToBalances = (acc: Map<string, number>, materialId?: string, warehouseId?: string, shelfId?: string, qty?: number) => {
    const mat = String(materialId || '').trim();
    const wh = String(warehouseId || '').trim();
    const shelf = String(shelfId || '').trim();
    const amount = Number(qty || 0);
    if (!mat || !wh || !shelf || !Number.isFinite(amount) || amount === 0) return;
    const key = `${mat}||${wh}||${shelf}`;
    acc.set(key, (acc.get(key) || 0) + amount);
    };

    const balances = inventoryMovements.reduce<Map<string, number>>((acc, movement) => {
    let materialId = String(movement.materialId || '').trim();
    let warehouseId = String(movement.warehouseId || '').trim();
    let shelfId = String(movement.shelfId || '').trim();
    const referenceType = String(movement.referenceType || '').trim().toLowerCase();
    const referenceId = String(movement.referenceId || '').trim();
    const quantity = Number(movement.quantityIn || 0) - Number(movement.quantityOut || 0);

    // Ignore transfer document movements from raw log and rebuild them from document data below.
    if (transferRefTypes.has(referenceType)) {
      return acc;
    }

    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>());

    // Rebuild transfer-document effects from canonical document state.
    internalTransferDocuments
    .filter((doc) => String(doc.status || 'active') === 'active')
    .forEach((doc) => {
      const receiptStatus = String(doc.receiptStatus || 'pending').trim();
      (doc.items || []).forEach((item) => {
        const baseReceived = receiptStatus === 'pending'
          ? Number(item.quantity || 0)
          : Number(item.receivedQuantity ?? item.quantity ?? 0);
        const overApproved = Number(
          item.overApprovedQuantity ?? (item.overageStatus === 'approved' ? item.overReceivedQuantity ?? 0 : 0)
        );
        const safeBaseReceived = Math.max(0, baseReceived);
        const safeOverApproved = Math.max(0, overApproved);
        const toWarehouseId = doc.enableWarehouseTransfer ? item.toWarehouseId : item.fromWarehouseId;
        const toShelfId = doc.enableShelfTransfer ? item.toShelfId : item.fromShelfId;
        const savedDistributions = Array.isArray(item.receiptDistributions)
          ? item.receiptDistributions
              .map((entry) => ({
                shelfId: String((entry as any)?.shelfId || '').trim(),
                quantity: Number((entry as any)?.quantity || 0),
              }))
              .filter((entry) => entry.shelfId && Number.isFinite(entry.quantity) && entry.quantity > 0)
          : [];

        if (safeBaseReceived > 0) {
          addToBalances(balances, item.materialId, item.fromWarehouseId, item.fromShelfId, -safeBaseReceived);

          if (savedDistributions.length > 0 && receiptStatus !== 'pending') {
            const distributedTotal = savedDistributions.reduce((sum, entry) => sum + entry.quantity, 0);
            const factor = distributedTotal > 0 ? safeBaseReceived / distributedTotal : 0;
            savedDistributions.forEach((entry) => {
              addToBalances(balances, item.materialId, toWarehouseId, entry.shelfId, entry.quantity * factor);
            });
          } else {
            addToBalances(balances, item.materialId, toWarehouseId, toShelfId, safeBaseReceived);
          }
        }

        if (safeOverApproved > 0) {
          const overageSourceShelfId = item.overageSourceShelfId || item.fromShelfId;
          addToBalances(balances, item.materialId, item.fromWarehouseId, overageSourceShelfId, -safeOverApproved);

          if (savedDistributions.length > 0 && receiptStatus !== 'pending') {
            const distributedTotal = savedDistributions.reduce((sum, entry) => sum + entry.quantity, 0);
            const factor = distributedTotal > 0 ? safeOverApproved / distributedTotal : 0;
            savedDistributions.forEach((entry) => {
              addToBalances(balances, item.materialId, toWarehouseId, entry.shelfId, entry.quantity * factor);
            });
          } else {
            addToBalances(balances, item.materialId, toWarehouseId, toShelfId, safeOverApproved);
          }
        }
      });
    });

    stockLocationsByMaterial = Array.from(balances.entries()).reduce<Record<string, StockLocationBalance[]>>((acc, [key, quantity]) => {
    if (quantity <= 0) return acc;

    const [materialId, warehouseId, shelfId] = key.split('||');
    if (!materialId || !warehouseId || !shelfId) return acc;

    const list = acc[materialId] || [];
    list.push({
      materialId,
      warehouseId,
      warehouseName: warehouseNameById.get(warehouseId) || warehouseId,
      shelfId,
      shelfName: shelfNameByCompositeId.get(`${warehouseId}||${shelfId}`) || shelfId,
      quantity,
    });
    acc[materialId] = list;
    return acc;
    }, {});
    
  }

  const availableMaterialIds = availableOnly ? Object.keys(stockLocationsByMaterial) : undefined;
  const materialsResult = await pgGetMaterials({ page, pageSize, search, sortKey, sortDir, hasAlternativesOnly, availableOnly, materialIds: availableMaterialIds, materialFilters, materialFilterModes });
  const materials: ProductionItem[] = materialsResult.items as ProductionItem[];

  return (
    <ListManager
      items={materials}
      title={tLists?.manageMaterials ?? "إدارة المواد"}
      description={tLists?.manageMaterialsDescription ?? "إضافة وتعديل وحذف المواد المستخدمة في تقارير الإنتاج."}
      itemType="material"
      storeModuleEnabled={storeModuleEnabled}
      categories={categories}
      itemGroups={itemGroups}
      warehouses={warehouses}
      warehousesEnabled={warehousesEnabled}
      stockLocationsByMaterial={stockLocationsByMaterial}
      internalTransferDocuments={internalTransferDocuments}
      inventoryMovements={inventoryMovements as any}
      unitDefinitions={unitDefinitions}
      productShapeDefinitions={productShapeDefinitions.map((entry) => ({ id: String(entry.id || ""), name: String(entry.name || "").trim() })).filter((entry) => entry.id && entry.name)}
      realEstateProjects={realEstateProjects}
      chartOfAccounts={chartOfAccounts}
      t={tLists}
      tGlobal={tGlobal}
      currencySymbol={currencySymbol}
      serverPagination={ {
        enabled: true,
        page: materialsResult.page,
        pageSize: materialsResult.pageSize,
        totalItems: materialsResult.totalItems,
        totalPages: materialsResult.totalPages,
        search,
        hasAlternativesOnly,
        availableOnly,
        materialFilters,
        materialFilterModes,
        sortKey,
        sortDir,
        withBarcodeCount: Number((materialsResult as any).withBarcodeCount || 0),
        totalSaleValue: Number((materialsResult as any).totalSaleValue || 0),
      } }
    />
  );
}
