import type { Metadata } from 'next';
import { redirect } from 'next/navigation';

import PosSales from '@/components/admin/pos-sales';
import { getSession } from '@/lib/auth';

import { hasEmployeePermission } from '@/lib/employee-permissions';
import { getCurrentLocale, getTranslations } from '@/lib/i18n';
import {
  pgGetCurrencies,
  pgGetCampaigns,
  pgGetCustomerPricing,
  pgGetCustomers,
  pgGetEmployees,
  pgGetGeneralBanks,
  pgGetInventoryMovements,
  pgGetInvoices,
  pgGetItemGroups,
  pgGetItemUnits,
  pgGetMaterials,
  pgGetPayments,
  pgGetPurchaseOrders,
  pgGetSettings,
  pgGetSalesReps,
  pgGetSupplierPayments,
  pgGetSuppliers,
  pgGetActiveWarehouses,
} from '@/lib/postgres/data-access';

export const metadata: Metadata = {
  title: 'نقطة البيع',
  description: 'واجهة نقطة البيع للمبيعات.',
};

export const dynamic = 'force-dynamic';

const toList = <T,>(value: { items?: T[] } | T[] | null | undefined): T[] => {
  if (Array.isArray(value)) return value;
  if (Array.isArray(value?.items)) return value.items;
  return [];
};

const toBooleanOrDefault = (value: unknown, defaultValue = false) => {
  if (value === undefined || value === null || value === '') return defaultValue;
  if (typeof value === 'boolean') return value;
  if (typeof value === 'number') {
    if (value === 1) return true;
    if (value === 0) return false;
    return defaultValue;
  }
  if (typeof value === 'string') {
    const normalized = value.trim().toLowerCase();
    if (['true', '1', 'yes', 'on'].includes(normalized)) return true;
    if (['false', '0', 'no', 'off'].includes(normalized)) return false;
  }
  return defaultValue;
};

const isEnabled = (value: unknown) => toBooleanOrDefault(value, false);
const isTruthySetting = (value: unknown, defaultValue = true) => toBooleanOrDefault(value, defaultValue);

async function safeLoad<T>(label: string, loader: () => Promise<T>, fallback: T): Promise<T> {
  try {
    return await loader();
  } catch (error) {
    console.error(`[SalesPosPage] Failed to load ${label}:`, error);
    return fallback;
  }
}

export default async function SalesPosPage() {
  const [session, locale] = await Promise.all([getSession(), getCurrentLocale()]);

  if (!session?.user) {
    redirect('/login');
  }

  const messages = (getTranslations(locale) ?? {}) as any;
  const t = {
    ...(messages?.Sales ?? messages?.SalesInvoice ?? messages?.SalesPage ?? {}),
    PaymentMethods: messages?.PaymentMethods ?? {},
  };
  const tStatement = messages?.PartyStatement ?? {};
  const tGlobal = messages?.Global ?? {};

  let rawCustomers: any[] = [];
  let rawSuppliers: any[] = [];
  let rawMaterials: any[] = [];
  let rawCampaigns: any[] = [];
  let rawItemUnits: any[] = [];
  let rawItemGroups: any[] = [];
  let rawInvoices: any[] = [];
  let rawOrders: any[] = [];
  let rawPayments: any[] = [];
  let rawSupplierPayments: any[] = [];
  let rawBanks: any[] = [];
  let rawCurrencies: any[] = [];
  let rawCustomerPricing: any[] = [];
  let rawSalesReps: any[] = [];
  let rawWarehouses: any[] = [];
  let rawInventoryMovements: any[] = [];
  let rawEmployees: any[] = [];
  let settings: Record<string, any> = {};

  
  const emptyPagedResult = { items: [] as any[] };

  const [
  settingsResult,
  customersResult,
  materialsResult,
  campaignsResult,
  itemUnitsResult,
  itemGroupsResult,
  currenciesResult,
  pricingResult,
  ] = await Promise.all([
  safeLoad('settings', () => pgGetSettings(), {} as Record<string, any>),
  safeLoad('customers', () => pgGetCustomers({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('materials', () => pgGetMaterials({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('campaigns', () => pgGetCampaigns(), [] as any[]),
  safeLoad('item units', () => pgGetItemUnits({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('item groups', () => pgGetItemGroups({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('currencies', () => pgGetCurrencies({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('customer pricing', () => pgGetCustomerPricing({ page: 1, pageSize: 1000 }), emptyPagedResult),
  ]);

  settings = (settingsResult ?? {}) as Record<string, any>;
  rawCustomers = toList(customersResult);
  rawMaterials = toList(materialsResult);
  rawCampaigns = toList(campaignsResult as any);
  rawItemUnits = toList(itemUnitsResult);
  rawItemGroups = toList(itemGroupsResult);
  rawCurrencies = toList(currenciesResult);
  rawCustomerPricing = toList(pricingResult);

  // Determine if warehouses are enabled early to conditionally load related data
  const warehousesEnabledCheck = isEnabled(settings?.warehousesEnabled);

  // Only load warehouses and inventory movements if warehouses are enabled
  const loadsToPerform = warehousesEnabledCheck
    ? [
        safeLoad('warehouses', () => pgGetActiveWarehouses(), emptyPagedResult),
        safeLoad('employees', () => pgGetEmployees({ page: 1, pageSize: 1000 }), emptyPagedResult),
        safeLoad('inventory movements', () => pgGetInventoryMovements({ page: 1, pageSize: 1000 }), emptyPagedResult),
      ]
    : [
        safeLoad('warehouses', () => Promise.resolve(emptyPagedResult), emptyPagedResult),
        safeLoad('employees', () => pgGetEmployees({ page: 1, pageSize: 1000 }), emptyPagedResult),
      ];

  const [warehousesResult, employeesResult, inventoryMovementsResult = emptyPagedResult] = await Promise.all(loadsToPerform);

  rawWarehouses = warehousesEnabledCheck ? toList(warehousesResult) : [];
  rawEmployees = toList(employeesResult);
  rawInventoryMovements = warehousesEnabledCheck ? toList(inventoryMovementsResult) : [];

  const [
  suppliersResult,
  invoicesResult,
  ordersResult,
  paymentsResult,
  supplierPaymentsResult,
  banksResult,
  salesRepsResult,
  ] = await Promise.all([
  safeLoad('suppliers', () => pgGetSuppliers({ page: 1, pageSize: 1000 }), emptyPagedResult),
  safeLoad('invoices', () => pgGetInvoices({ page: 1, pageSize: 500 }), emptyPagedResult),
  safeLoad('purchase orders', () => pgGetPurchaseOrders({ page: 1, pageSize: 500 }), emptyPagedResult),
  safeLoad('payments', () => pgGetPayments({ page: 1, pageSize: 500 }), emptyPagedResult),
  safeLoad('supplier payments', () => pgGetSupplierPayments({ page: 1, pageSize: 500 }), emptyPagedResult),
  safeLoad('general banks', () => pgGetGeneralBanks(), [] as any[]),
  safeLoad('sales reps', () => pgGetSalesReps({ page: 1, pageSize: 1000 }), emptyPagedResult),
  ]);

  rawSuppliers = toList(suppliersResult);
  rawInvoices = toList(invoicesResult);
  rawOrders = toList(ordersResult);
  rawPayments = toList(paymentsResult);
  rawSupplierPayments = toList(supplierPaymentsResult);
  rawBanks = toList(banksResult as any);
  rawSalesReps = toList(salesRepsResult);
  

  if (!hasEmployeePermission(session.user, settings, 'admin.pos')) {
    redirect('/');
  }

  const warehousesEnabled = isEnabled(settings?.warehousesEnabled);
  const allowOutOfStockSales = isEnabled(settings?.allowOutOfStockSales);
  const defaultWarehouseId = warehousesEnabled ? String(settings?.defaultSalesWarehouseId || '').trim() : '';
  const defaultShelfId = warehousesEnabled ? String(settings?.defaultSalesShelfId || '').trim() : '';

  const allowedWarehouseIds = session.user.role === 'admin'
    ? null
    : new Set((session.user.warehouseIds || []).map((warehouseId) => String(warehouseId || '').trim()).filter(Boolean));

  const filteredWarehouses = warehousesEnabled
    ? rawWarehouses.filter((warehouse) => {
        if (!allowedWarehouseIds) return true;
        return allowedWarehouseIds.has(String(warehouse?.id || '').trim());
      })
    : [];

  const warehouseNameById = new Map<string, string>();
  const shelfNameById = new Map<string, string>();
  filteredWarehouses.forEach((warehouse) => {
    const warehouseId = String(warehouse?.id || '').trim();
    if (!warehouseId) return;
    warehouseNameById.set(warehouseId, String(warehouse?.name || warehouseId));
    (warehouse?.shelves || []).forEach((shelf: any) => {
      const shelfId = String(shelf?.id || '').trim();
      if (shelfId) {
        shelfNameById.set(shelfId, String(shelf?.name || shelfId));
      }
    });
  });

  const stockByMaterialAndLocation = new Map<string, number>();
  if (warehousesEnabled) {
    rawInventoryMovements.forEach((movement) => {
      const materialId = String(movement?.materialId || '').trim();
      const warehouseId = String(movement?.warehouseId || '').trim();
      const shelfId = String(movement?.shelfId || '').trim();

      if (!materialId || !warehouseId || !shelfId) return;
      if (allowedWarehouseIds && !allowedWarehouseIds.has(warehouseId)) return;

      const quantityIn = Number(movement?.quantityIn || 0);
      const quantityOut = Number(movement?.quantityOut || 0);
      const fallbackQuantity = Number(movement?.quantity || 0);
      const direction = String(movement?.direction || '').trim().toLowerCase();
      const signedQty = quantityIn !== 0 || quantityOut !== 0
        ? quantityIn - quantityOut
        : (direction === 'out' ? -fallbackQuantity : fallbackQuantity);

      if (!Number.isFinite(signedQty) || signedQty === 0) return;

      const key = `${materialId}||${warehouseId}||${shelfId}`;
      stockByMaterialAndLocation.set(key, (stockByMaterialAndLocation.get(key) || 0) + signedQty);
    });
  }

  const stockLocationsByMaterial = Array.from(stockByMaterialAndLocation.entries()).reduce<Record<string, any[]>>((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: shelfNameById.get(shelfId) || shelfId,
      quantity,
    });
    acc[materialId] = list.sort((a, b) => Number(b.quantity || 0) - Number(a.quantity || 0));
    return acc;
  }, {});

  const defaultCurrency = rawCurrencies.find((currency) => isEnabled(currency?.isDefault)) || rawCurrencies[0] || null;
  const currencySymbol = String(defaultCurrency?.symbol || '$');
  const printerConfigs = Array.isArray(settings?.printerConfigs)
    ? settings.printerConfigs.filter((entry: any) => entry && typeof entry === 'object')
    : [];
  const printSections = Array.isArray(settings?.printSections)
    ? settings.printSections.filter((entry: any) => entry && typeof entry === 'object')
    : [];
  const restaurantPosAreas = Array.isArray(settings?.restaurantPosAreas)
    ? settings.restaurantPosAreas.filter((entry: any) => entry && typeof entry === 'object')
    : [];
  const restaurantPosTables = Array.isArray(settings?.restaurantPosTables)
    ? settings.restaurantPosTables.filter((entry: any) => entry && typeof entry === 'object')
    : [];

  // Get current employee cash account (session.user is guaranteed to exist after the earlier check)
  const currentEmployee = rawEmployees.find((emp: any) => emp.id === (session.user as any).id);
  const employeeCashAccountCode = String(currentEmployee?.employeeCashAccountCode || '').trim();

  const salesReps = [
    ...rawSalesReps.map((rep: any) => ({ id: rep.id, name: rep.name })),
    ...rawEmployees
      .filter((employee) => {
        const businessRole = String(employee?.businessRole || '').trim().toLowerCase();
        return businessRole === 'مندوب مبيعات' || businessRole === 'sales rep' || businessRole === 'sales-rep';
      })
      .filter((employee) => !rawSalesReps.find((rep: any) => rep.id === employee.id))
      .map((employee) => ({ id: employee.id, name: employee.name }))
  ];

  return (
    <div data-pos-fullscreen="true" className="min-h-screen w-full overflow-hidden bg-background">
        <PosSales
          customers={rawCustomers}
          suppliers={rawSuppliers}
          materials={rawMaterials}
          itemUnits={rawItemUnits}
          itemGroups={rawItemGroups}
          invoices={rawInvoices}
          orders={rawOrders}
          customerPayments={rawPayments}
          supplierPayments={rawSupplierPayments}
          campaigns={rawCampaigns}
          banks={rawBanks.filter((bank) => bank && typeof bank.id === 'string' && bank.isActive !== false)}
          currencies={rawCurrencies}
          defaultCurrency={defaultCurrency}
          allCustomerPricing={rawCustomerPricing}
          salesReps={salesReps}
          warehouses={filteredWarehouses}
          warehouseConfig={{
            enabled: warehousesEnabled,
            allowOutOfStockSales,
            defaultWarehouseId,
            defaultShelfId,
          }}
          stockLocationsByMaterial={stockLocationsByMaterial}
          t={t}
          tStatement={tStatement}
          tGlobal={tGlobal}
          locale={locale}
          currencySymbol={currencySymbol}
          cashierName={session.user.name}
          employeeCashAccountCode={employeeCashAccountCode}
          scaleSettings={{
            mode: (settings?.scaleMode === 'disabled' || !settings?.scaleMode ? 'manual' : settings.scaleMode) as 'manual' | 'hid' | 'serial',
            readRegex: String(settings?.scaleReadRegex || ''),
            decimalSeparator: (settings?.scaleDecimalSeparator || 'auto') as 'auto' | 'dot' | 'comma',
            hidMinLength: Number(settings?.scaleHidMinLength || 3),
            serialBaudRate: Number(settings?.scaleSerialBaudRate || 9600),
            serialDataBits: Number(settings?.scaleSerialDataBits || 8),
            serialStopBits: Number(settings?.scaleSerialStopBits || 1),
            serialParity: (settings?.scaleSerialParity || 'none') as 'none' | 'even' | 'odd',
            serialAutoConnect: isEnabled(settings?.scaleSerialAutoConnect),
          }}
          posPaymentMethods={{
            allowCash: settings?.posAllowCash !== false,
            allowVisa: settings?.posAllowVisa !== false,
            allowReceivables: settings?.posAllowReceivables !== false,
            defaultVisaBankAccountId: String(settings?.defaultPosVisaBankAccountId || '').trim(),
          }}
          visibleColumns={{
            itemNumber: isTruthySetting(settings?.posShowItemNumberColumn, true),
            unit: isTruthySetting(settings?.posShowUnitColumn, true),
            description: isTruthySetting(settings?.posShowDescriptionColumn, true),
            barcode: isTruthySetting(settings?.posShowBarcodeColumn, true),
            quantity: isTruthySetting(settings?.posShowQuantityColumn, true),
            price: isTruthySetting(settings?.posShowPriceColumn, true),
            itemDiscount: isTruthySetting(settings?.posShowItemDiscountColumn, true),
            bonus: isTruthySetting(settings?.posShowBonusColumn, true),
            total: isTruthySetting(settings?.posShowTotalColumn, true),
            actions: isTruthySetting(settings?.posShowActionsColumn, true),
            weighedItemsButton: settings?.posShowWeighedItemsButton === true,
          }}
          printingSettings={{
            customPrintersEnabled: isEnabled(settings?.customPrintersEnabled),
            printerAutoPrintEnabled: isEnabled(settings?.printerAutoPrintEnabled),
            printTransportMode: settings?.printTransportMode === 'native-bridge' ? 'native-bridge' : 'browser',
            defaultCustomerReceiptPrinterId: String(settings?.defaultCustomerReceiptPrinterId || ''),
            printHeaderLeftText: String(settings?.printHeaderLeftText || ''),
            printHeaderCenterText: String(settings?.printHeaderCenterText || ''),
            printHeaderRightText: String(settings?.printHeaderRightText || ''),
            printHeaderText: String(settings?.printHeaderText || ''),
            printFooterText: String(settings?.printFooterText || ''),
            printerConfigs,
            printSections,
          }}
          restaurantConfig={{
            enabled: isEnabled(settings?.restaurantPosEnabled),
            areasEnabled: isTruthySetting(settings?.restaurantPosAreasEnabled, true),
            splitBillEnabled: isTruthySetting(settings?.restaurantPosSplitBillEnabled, true),
            mergeTablesEnabled: isTruthySetting(settings?.restaurantPosMergeTablesEnabled, true),
            transferItemEnabled: isTruthySetting(settings?.restaurantPosTransferItemEnabled, true),
            partialCheckoutEnabled: isTruthySetting(settings?.restaurantPosPartialCheckoutEnabled, true),
            kotEnabled: isTruthySetting(settings?.restaurantPosKotEnabled, true),
            autoReserveMinutes: Math.max(0, Number(settings?.restaurantPosAutoReserveMinutes || 90)),
            defaultGuestCount: Math.max(1, Number(settings?.restaurantPosDefaultGuestCount || 2)),
            areas: restaurantPosAreas,
            tables: restaurantPosTables,
          }}
        />
      </div>
  );
}
