import { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Modal,
  Pressable,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';
import api from '../../core/api';
import { PosCustomerLookup } from '../../components/pos/PosCustomerLookup';
import { PosDiscountPanel } from '../../components/pos/PosDiscountPanel';
import { PosPatientLookup } from '../../components/pos/PosPatientLookup';
import { PosPaymentLines } from '../../components/pos/PosPaymentLines';
import { PosPrescriptionModal, type PrescriptionCartPayload } from '../../components/pos/PosPrescriptionModal';
import { PosReceiptModal } from '../../components/pos/PosReceiptModal';
import { PosReconciliationModal } from '../../components/pos/PosReconciliationModal';
import { PosReturnModal } from '../../components/pos/PosReturnModal';
import { PosHeldSalesModal } from '../../components/pos/PosHeldSalesModal';
import { PosSessionDashboard } from '../../components/pos/PosSessionDashboard';
import { AppButton } from '../../components/ui/AppButton';
import { ScreenLayout } from '../../components/ui/ScreenLayout';
import { RecordCard } from '../../components/ui/RecordCard';
import { useAuth } from '../../context/AuthContext';
import { useSubscriptionRestriction } from '../../hooks/useSubscriptionRestriction';
import { colors, radii, spacing } from '../../constants/theme';
import {
  createPaymentLine,
  PosPaymentDevice,
  PosCustomerOption,
  PosPaymentLine,
  PosReceiptData,
  PosReconciliation,
  PosSale,
  PosSession,
} from '../../types/pos';
import {
  canAddProductToCart,
  formatMoney,
  PosCartLine,
  PosCatalogItem,
  productRequiresStock,
  productStockAvailable,
} from '../../utils/posStock';
import { computePosTotals, getDiscountLabel, isScPwdDiscount, type DiscountType } from '../../utils/posTotals';
import { applyHoldPayload, buildHoldPayload, type HoldPayload } from '../../utils/posSaleState';
import type { PosHeldSale } from '../../types/posHeld';

type PosState = {
  session?: PosSession | null;
  catalog?: PosCatalogItem[];
  devices?: PosPaymentDevice[];
  customers?: PosCustomerOption[];
  reconciliation?: PosReconciliation | null;
  held_sales?: PosHeldSale[];
};

export function PosScreen() {
  const { roles, userName } = useAuth();
  const { readOnly, message: restrictedMessage } = useSubscriptionRestriction();
  const canManageTransactions = roles.includes('owner') || roles.includes('doctor');

  if (readOnly) {
    return (
      <ScreenLayout title="POS Register" subtitle="Point of sale" hideSubscriptionBanner>
        <RecordCard
          title="POS unavailable"
          subtitle={restrictedMessage}
          badge="locked"
        />
      </ScreenLayout>
    );
  }

  const [loading, setLoading] = useState(true);
  const [opening, setOpening] = useState(false);
  const [completing, setCompleting] = useState(false);
  const [holding, setHolding] = useState(false);
  const [connectingDevice, setConnectingDevice] = useState(false);
  const [capturingIndex, setCapturingIndex] = useState(-1);
  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');

  const [session, setSession] = useState<PosSession | null>(null);
  const [devices, setDevices] = useState<PosPaymentDevice[]>([]);
  const [selectedDeviceId, setSelectedDeviceId] = useState('');
  const [catalog, setCatalog] = useState<PosCatalogItem[]>([]);
  const [cart, setCart] = useState<PosCartLine[]>([]);
  const [payments, setPayments] = useState<PosPaymentLine[]>([createPaymentLine('cash', 0)]);
  const [search, setSearch] = useState('');
  const [openingFloat, setOpeningFloat] = useState('0');
  const [discountType, setDiscountType] = useState<DiscountType>('none');
  const [discountValue, setDiscountValue] = useState('0');
  const [scPwdIdNumber, setScPwdIdNumber] = useState('');
  const [taxRate, setTaxRate] = useState('12');
  const [selectedPatientId, setSelectedPatientId] = useState('');
  const [prescriptionId, setPrescriptionId] = useState<number | null>(null);
  const [reconciliation, setReconciliation] = useState<PosReconciliation | null>(null);
  const [amountTendered, setAmountTendered] = useState('0');
  const [customers, setCustomers] = useState<PosCustomerOption[]>([]);
  const [saleCustomerType, setSaleCustomerType] = useState<'walk_in' | 'customer'>('walk_in');
  const [selectedCustomerId, setSelectedCustomerId] = useState('');

  const [salesModalOpen, setSalesModalOpen] = useState(false);
  const [salesLoading, setSalesLoading] = useState(false);
  const [sessionSales, setSessionSales] = useState<PosSale[]>([]);

  const [reasonModalOpen, setReasonModalOpen] = useState(false);
  const [reasonMode, setReasonMode] = useState<'void' | 'edit'>('void');
  const [reasonText, setReasonText] = useState('');
  const [reasonSaving, setReasonSaving] = useState(false);
  const [selectedSale, setSelectedSale] = useState<PosSale | null>(null);
  const [editNotes, setEditNotes] = useState('');
  const [editPayments, setEditPayments] = useState<PosSale['payments']>([]);

  const [deviceModalOpen, setDeviceModalOpen] = useState(false);
  const [newDeviceName, setNewDeviceName] = useState('Card Terminal');

  const [prescriptionModalOpen, setPrescriptionModalOpen] = useState(false);
  const [receiptModalOpen, setReceiptModalOpen] = useState(false);
  const [receiptData, setReceiptData] = useState<PosReceiptData | null>(null);
  const [returnModalOpen, setReturnModalOpen] = useState(false);
  const [returnSale, setReturnSale] = useState<PosSale | null>(null);
  const [reconciliationModalOpen, setReconciliationModalOpen] = useState(false);
  const [heldSales, setHeldSales] = useState<PosHeldSale[]>([]);
  const [heldSalesModalOpen, setHeldSalesModalOpen] = useState(false);
  const [heldSalesLoading, setHeldSalesLoading] = useState(false);

  const loadDashboard = useCallback(async (sessionId?: number) => {
    const id = sessionId ?? session?.id;
    if (!id) return;
    try {
      const { data } = await api.get('/pos/dashboard', { params: { session_id: id } });
      setReconciliation(data.reconciliation || null);
    } catch {
      // keep existing reconciliation from /pos/state
    }
  }, [session?.id]);

  const load = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const { data } = await api.get<PosState>('/pos/state');
      setSession(data.session || null);
      setCatalog(data.catalog || []);
      setDevices(data.devices || []);
      setCustomers(data.customers || []);
      setReconciliation(data.reconciliation || null);
      setHeldSales(data.held_sales || []);
      if (data.session?.connected_device_id) {
        setSelectedDeviceId(String(data.session.connected_device_id));
      }
      if (data.session) {
        await loadDashboard(data.session.id);
      }
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to load POS.');
    } finally {
      setLoading(false);
    }
  }, [loadDashboard]);

  useEffect(() => {
    load();
  }, [load]);

  const filteredCatalog = useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return catalog;
    return catalog.filter((product) =>
      [product.name, product.sku, product.barcode].some((value) =>
        String(value || '').toLowerCase().includes(q),
      ),
    );
  }, [catalog, search]);

  const totals = useMemo(
    () =>
      computePosTotals(cart, {
        discountType,
        discountValue: Number(discountValue) || 0,
        scPwdIdNumber,
        taxRate: Number(taxRate) || 0,
      }),
    [cart, discountType, discountValue, scPwdIdNumber, taxRate],
  );

  const paidTotal = useMemo(
    () => payments.reduce((sum, p) => sum + (Number(p.amount) || 0), 0),
    [payments],
  );
  const paymentsBalanced = Math.abs(paidTotal - totals.total) < 0.01;
  const cashDue = useMemo(
    () =>
      payments
        .filter((p) => p.payment_mode === 'cash')
        .reduce((sum, p) => sum + (Number(p.amount) || 0), 0),
    [payments],
  );

  const resetPaymentsForTotal = useCallback((total: number) => {
    setPayments([createPaymentLine('cash', total)]);
    setAmountTendered(String(total));
  }, []);

  const openSession = async () => {
    setOpening(true);
    setError('');
    try {
      const { data } = await api.post('/pos/sessions/open', {
        opening_float: Number(openingFloat) || 0,
      });
      setSession(data.session || null);
      setCatalog(data.catalog || []);
      setDevices(data.devices || []);
      setCustomers(data.customers || []);
      resetPaymentsForTotal(0);
      setSuccess(data.message || 'Session opened.');
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to open session.');
    } finally {
      setOpening(false);
    }
  };

  const registerDevice = async () => {
    if (!newDeviceName.trim()) return;
    setError('');
    try {
      const { data } = await api.post('/pos/devices', {
        name: newDeviceName.trim(),
        device_type: 'card_terminal',
        provider: 'Generic',
      });
      setDevices((current) => [...current, data.device]);
      setSelectedDeviceId(String(data.device.id));
      setDeviceModalOpen(false);
      setSuccess(data.message || 'Device registered.');
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to register device.');
    }
  };

  const connectDevice = async () => {
    if (!selectedDeviceId) return;
    setConnectingDevice(true);
    setError('');
    try {
      const { data } = await api.post(`/pos/devices/${selectedDeviceId}/connect`);
      setSession(data.session || null);
      setSuccess(data.message || 'Device connected.');
      await load();
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to connect device.');
    } finally {
      setConnectingDevice(false);
    }
  };

  const disconnectDevice = async () => {
    setConnectingDevice(true);
    setError('');
    try {
      const { data } = await api.post('/pos/devices/disconnect');
      setSession(data.session || null);
      setSuccess(data.message || 'Device disconnected.');
      await load();
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to disconnect device.');
    } finally {
      setConnectingDevice(false);
    }
  };

  const capturePaymentLine = async (index: number) => {
    const payment = payments[index];
    const deviceId = session?.connected_device_id;
    if (!deviceId || !payment?.amount) return;

    setCapturingIndex(index);
    setError('');
    try {
      const { data } = await api.post(`/pos/devices/${deviceId}/capture`, {
        payment_mode: payment.payment_mode,
        amount: payment.amount,
      });
      setPayments((current) =>
        current.map((line, i) =>
          i === index ? { ...line, ...data.capture, capture_mode: 'device' as const } : line,
        ),
      );
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Device capture failed.');
    } finally {
      setCapturingIndex(-1);
    }
  };

  const addToCart = (product: PosCatalogItem) => {
    setCart((current) => {
      const existing = current.find((line) => line.service_product_id === product.id);
      const nextQty = (existing?.quantity || 0) + 1;
      if (!canAddProductToCart(product, nextQty)) {
        setError(`Insufficient stock for ${product.name}.`);
        return current;
      }
      setError('');
      const nextCart = existing
        ? current.map((line) =>
            line.service_product_id === product.id
              ? { ...line, quantity: line.quantity + 1 }
              : line,
          )
        : [
            ...current,
            {
              service_product_id: product.id,
              name: product.name,
              type: product.type,
              unit_price: Number(product.price),
              quantity: 1,
              track_inventory: product.track_inventory,
              stock_available: product.stock_available,
            },
          ];
      const t = computePosTotals(nextCart, {
        discountType,
        discountValue: Number(discountValue) || 0,
        scPwdIdNumber,
        taxRate: Number(taxRate) || 0,
      });
      resetPaymentsForTotal(t.total);
      return nextCart;
    });
  };

  const barcodeSearch = async () => {
    const q = search.trim();
    if (!q) return;
    try {
      const { data } = await api.get('/pos/products/search', {
        params: { q, exact: /^[A-Za-z0-9\-]+$/.test(q) ? 1 : 0 },
      });
      const products = (data.products || []) as PosCatalogItem[];
      if (products.length === 1) {
        addToCart(products[0]);
        setSearch('');
        setSuccess(`Added ${products[0].name}`);
      } else if (products.length > 1) {
        setCatalog(products);
      }
    } catch {
      // client filter fallback
    }
  };

  const onPrescriptionLoaded = (data: PrescriptionCartPayload) => {
    setPrescriptionId(data.prescription.id);
    setSelectedPatientId(String(data.prescription.patient_id));
    for (const item of data.items) {
      if (item.service_product_id) {
        addToCart({
          id: item.service_product_id,
          name: item.name,
          type: item.type || 'product',
          price: item.unit_price,
          track_inventory: item.track_inventory,
          stock_available: item.stock_available,
        } as PosCatalogItem);
      } else {
        setCart((current) => [
          ...current,
          {
            service_product_id: 0,
            name: item.name,
            type: 'product',
            unit_price: item.unit_price,
            quantity: item.quantity,
            track_inventory: false,
            stock_available: null,
          },
        ]);
      }
    }
    setSuccess('Prescription items added to cart.');
  };

  function saleStateHelpers() {
    return {
      setCart,
      setSaleCustomerType,
      setSelectedCustomerId,
      setSelectedPatientId,
      setPrescriptionId,
      setDiscountType,
      setDiscountValue,
      setScPwdIdNumber,
      setTaxRate,
      setAmountTendered,
      setPayments,
    };
  }

  async function refreshHeldSales() {
    if (!session) return;
    try {
      const { data } = await api.get<{ held_sales: PosHeldSale[] }>('/pos/holds');
      setHeldSales(data.held_sales || []);
    } catch {
      setHeldSales([]);
    }
  }

  async function openHeldSalesModal() {
    setHeldSalesModalOpen(true);
    setHeldSalesLoading(true);
    await refreshHeldSales();
    setHeldSalesLoading(false);
  }

  async function putSaleOnHold() {
    if (!cart.length) return;
    setHolding(true);
    setError('');
    try {
      const { data } = await api.post<{ held_sales: PosHeldSale[]; message?: string }>(
        '/pos/holds',
        buildHoldPayload({
          cart,
          saleCustomerType,
          selectedCustomerId,
          selectedPatientId,
          prescriptionId,
          discountType,
          discountValue,
          scPwdIdNumber,
          taxRate,
          amountTendered,
          payments,
          totals,
        }),
      );
      setHeldSales(data.held_sales || []);
      setCart([]);
      clearSaleContext();
      resetPaymentsForTotal(0);
      setSuccess(data.message || 'Sale placed on hold.');
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to put sale on hold.');
    } finally {
      setHolding(false);
    }
  }

  async function resumeHeldSale(hold: PosHeldSale) {
    if (cart.length) {
      Alert.alert(
        'Replace current cart?',
        'The held sale will replace items in your current cart.',
        [
          { text: 'Cancel', style: 'cancel' },
          { text: 'Continue', onPress: () => doResumeHeldSale(hold) },
        ],
      );
      return;
    }
    await doResumeHeldSale(hold);
  }

  async function doResumeHeldSale(hold: PosHeldSale) {
    setError('');
    try {
      const { data } = await api.post<{ payload: HoldPayload; held_sales: PosHeldSale[]; message?: string }>(
        `/pos/holds/${hold.id}/resume`,
      );
      setHeldSales(data.held_sales || []);
      applyHoldPayload(data.payload, saleStateHelpers());
      setHeldSalesModalOpen(false);
      setSuccess(data.message || `Restored ${hold.hold_reference}`);
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to resume held sale.');
    }
  }

  async function discardHeldSale(hold: PosHeldSale) {
    Alert.alert('Discard held sale?', `Remove ${hold.hold_reference}?`, [
      { text: 'Cancel', style: 'cancel' },
      {
        text: 'Discard',
        style: 'destructive',
        onPress: async () => {
          try {
            const { data } = await api.delete<{ held_sales: PosHeldSale[]; message?: string }>(
              `/pos/holds/${hold.id}`,
            );
            setHeldSales(data.held_sales || []);
            setSuccess(data.message || 'Held sale discarded.');
          } catch (e: unknown) {
            const err = e as { response?: { data?: { message?: string } } };
            setError(err.response?.data?.message || 'Unable to discard.');
          }
        },
      },
    ]);
  }

  const openCashDrawer = async () => {
    try {
      const { data } = await api.post('/pos/cash-drawer/open');
      setSuccess(data.message || 'Drawer signal sent.');
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to open drawer.');
    }
  };

  const changeQty = (index: number, delta: number) => {
    setCart((current) => {
      const line = current[index];
      if (!line) return current;
      const nextQty = line.quantity + delta;
      if (delta > 0 && !canAddProductToCart(line, nextQty)) {
        setError(`Insufficient stock for ${line.name}.`);
        return current;
      }
      setError('');
      const nextCart =
        nextQty <= 0
          ? current.filter((_, itemIndex) => itemIndex !== index)
          : current.map((item, itemIndex) =>
              itemIndex === index ? { ...item, quantity: nextQty } : item,
            );
      const t = computePosTotals(nextCart, {
        discountType,
        discountValue: Number(discountValue) || 0,
        scPwdIdNumber,
        taxRate: Number(taxRate) || 0,
      });
      resetPaymentsForTotal(t.total);
      return nextCart;
    });
  };

  const updatePaymentLine = (index: number, patch: Partial<PosPaymentLine>) => {
    setPayments((current) =>
      current.map((line, i) => (i === index ? { ...line, ...patch } : line)),
    );
  };

  const addPaymentLine = () => {
    const remaining = Math.max(0, totals.total - paidTotal);
    setPayments((current) => [...current, createPaymentLine('cash', remaining)]);
  };

  const removePaymentLine = (index: number) => {
    setPayments((current) => (current.length <= 1 ? current : current.filter((_, i) => i !== index)));
  };

  const completeSale = async () => {
    if (!paymentsBalanced) {
      setError('Payment amounts must equal the order total.');
      return;
    }

    if (saleCustomerType === 'customer' && !selectedCustomerId) {
      setError('Select a customer or choose Walk-in.');
      return;
    }

    if (totals.scPwdRequired) {
      setError('Enter SC/PWD ID for discount.');
      return;
    }

    setCompleting(true);
    setError('');
    setSuccess('');
    try {
      const { data } = await api.post('/pos/sales', {
        items: cart.map(({ service_product_id, name, type, unit_price, quantity }) => ({
          service_product_id: service_product_id || null,
          name,
          type,
          unit_price,
          quantity,
        })),
        discount_type: discountType,
        discount_value: Number(discountValue) || 0,
        discount: totals.discount,
        sc_pwd_id_number: scPwdIdNumber || null,
        tax_rate: Number(taxRate) || 0,
        customer_id: saleCustomerType === 'customer' ? Number(selectedCustomerId) : null,
        patient_id: selectedPatientId ? Number(selectedPatientId) : null,
        prescription_id: prescriptionId ? Number(prescriptionId) : null,
        open_cash_drawer: cashDue > 0,
        payments: payments.map((p) => ({
          ...p,
          capture_mode:
            session?.connected_device_id && p.capture_mode === 'device' ? 'device' : 'manual',
        })),
        amount_tendered: cashDue > 0 ? Number(amountTendered) || 0 : null,
      });
      setCart([]);
      clearSaleContext();
      resetPaymentsForTotal(0);
      setSuccess(
        `${data.message || 'Sale completed.'} Order ${data.sales_order?.order_number || ''}. Change: ${formatMoney(data.change_amount || 0)}`,
      );
      await load();
      if (data.sales_order?.id) {
        await openReceipt(data.sales_order);
      }
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Sale failed.');
    } finally {
      setCompleting(false);
    }
  };

  function clearSaleContext() {
    setSaleCustomerType('walk_in');
    setSelectedCustomerId('');
    setSelectedPatientId('');
    setPrescriptionId(null);
    setDiscountType('none');
    setDiscountValue('0');
    setScPwdIdNumber('');
  }

  async function fetchSaleDetail(saleId: number): Promise<PosSale> {
    const { data } = await api.get<PosSale>(`/pos/sales/${saleId}`);
    return data;
  }

  async function openReceipt(sale: PosSale) {
    try {
      const { data } = await api.get<PosReceiptData>(`/pos/sales/${sale.id}/receipt`);
      setReceiptData(data);
      setReceiptModalOpen(true);
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to load receipt.');
    }
  }

  async function openReturnSale(sale: PosSale) {
    try {
      const detail = sale.lines?.length ? sale : await fetchSaleDetail(sale.id);
      setReturnSale(detail);
      setReturnModalOpen(true);
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to load sale.');
    }
  }

  const openSalesHistory = async () => {
    setSalesModalOpen(true);
    setSalesLoading(true);
    try {
      const { data } = await api.get('/pos/sales', {
        params: { session_id: session?.id, per_page: 50 },
      });
      const sales: PosSale[] = data.data || data;
      setSessionSales(
        await Promise.all(
          sales.map(async (sale) => {
            if (sale.lines?.length) return sale;
            try {
              return await fetchSaleDetail(sale.id);
            } catch {
              return sale;
            }
          }),
        ),
      );
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to load sales.');
    } finally {
      setSalesLoading(false);
    }
  };

  const openVoidSale = (sale: PosSale) => {
    setSelectedSale(sale);
    setReasonMode('void');
    setReasonText('');
    setReasonModalOpen(true);
  };

  const openEditSale = (sale: PosSale) => {
    setSelectedSale(sale);
    setReasonMode('edit');
    setReasonText('');
    setEditNotes(sale.notes || '');
    setEditPayments((sale.payments || []).map((p) => ({ ...p })));
    setReasonModalOpen(true);
  };

  const submitReasonModal = async () => {
    if (!selectedSale || reasonText.trim().length < 3) return;
    setReasonSaving(true);
    setError('');
    try {
      if (reasonMode === 'void') {
        await api.post(`/pos/sales/${selectedSale.id}/void`, { reason: reasonText.trim() });
        setSuccess('Sale voided.');
      } else {
        await api.put(`/pos/sales/${selectedSale.id}`, {
          reason: reasonText.trim(),
          notes: editNotes,
          payments: editPayments,
        });
        setSuccess('Sale updated.');
      }
      setReasonModalOpen(false);
      setSelectedSale(null);
      if (salesModalOpen) await openSalesHistory();
    } catch (e: unknown) {
      const err = e as { response?: { data?: { message?: string } } };
      setError(err.response?.data?.message || 'Unable to save changes.');
    } finally {
      setReasonSaving(false);
    }
  };

  if (loading) {
    return (
      <ScreenLayout title="POS Register">
        <Text style={styles.muted}>Loading POS...</Text>
      </ScreenLayout>
    );
  }

  return (
    <ScreenLayout title="POS Register" subtitle="Walk-in sales and split payments" onRefresh={load}>
      {error ? <Text style={styles.error}>{error}</Text> : null}
      {success ? <Text style={styles.success}>{success}</Text> : null}

      {!session ? (
        <View style={styles.card}>
          <Text style={styles.cardTitle}>Open register session</Text>
          <Text style={styles.muted}>Start a session before processing sales.</Text>
          <Text style={styles.label}>Opening float (cash)</Text>
          <TextInput
            style={styles.input}
            keyboardType="decimal-pad"
            value={openingFloat}
            onChangeText={setOpeningFloat}
          />
          <AppButton label={opening ? 'Opening...' : 'Open session'} icon="unlock" loading={opening} onPress={openSession} />
        </View>
      ) : (
        <>
          <PosSessionDashboard
            reconciliation={reconciliation}
            onRefresh={() => loadDashboard()}
          />

          <View style={styles.actionsRow}>
            <AppButton label="Reconcile" icon="payment" variant="secondary" onPress={() => setReconciliationModalOpen(true)} />
            <AppButton
              label={heldSales.length ? `On hold (${heldSales.length})` : 'On hold'}
              icon="forward"
              variant="secondary"
              onPress={openHeldSalesModal}
            />
            <AppButton label="Session sales" icon="invoice" variant="secondary" onPress={openSalesHistory} />
          </View>

          <View style={styles.card}>
            <Text style={styles.badge}>Session open</Text>
            <Text style={styles.muted}>{session.register?.name || 'Register'}</Text>
            {session.connected_device ? (
              <Text style={styles.connected}>Device: {session.connected_device.name}</Text>
            ) : null}

            <Text style={styles.label}>Payment device</Text>
            <View style={styles.devicePicker}>
              {devices.map((device) => (
                <Pressable
                  key={device.id}
                  style={[
                    styles.chip,
                    selectedDeviceId === String(device.id) && styles.chipActive,
                  ]}
                  onPress={() => setSelectedDeviceId(String(device.id))}
                >
                  <Text
                    style={[
                      styles.chipText,
                      selectedDeviceId === String(device.id) && styles.chipTextActive,
                    ]}
                  >
                    {device.name}
                  </Text>
                </Pressable>
              ))}
              <Pressable style={styles.chip} onPress={() => setDeviceModalOpen(true)}>
                <Text style={styles.chipText}>+ Register</Text>
              </Pressable>
            </View>
            <View style={styles.deviceActions}>
              <AppButton
                label="Connect"
                icon="payment"
                variant="secondary"
                loading={connectingDevice}
                disabled={!selectedDeviceId}
                onPress={connectDevice}
              />
              <AppButton
                label="Disconnect"
                icon="close"
                variant="secondary"
                loading={connectingDevice}
                disabled={!session.connected_device_id}
                onPress={disconnectDevice}
              />
            </View>

            <TextInput
              style={styles.input}
              placeholder="Search name, SKU, or barcode (submit to scan)"
              value={search}
              onChangeText={setSearch}
              onSubmitEditing={barcodeSearch}
              returnKeyType="search"
            />
            <View style={styles.rowActions}>
              <AppButton label="Prescription" icon="medication" variant="secondary" onPress={() => setPrescriptionModalOpen(true)} />
              <AppButton label="Drawer" icon="payment" variant="secondary" onPress={openCashDrawer} />
            </View>
            <View style={styles.catalog}>
              {filteredCatalog.map((product) => {
                const disabled = !canAddProductToCart(product);
                return (
                  <Pressable
                    key={product.id}
                    style={[styles.product, disabled && styles.productDisabled]}
                    disabled={disabled}
                    onPress={() => addToCart(product)}
                  >
                    <Text style={styles.productType}>{product.type}</Text>
                    <Text style={styles.productName}>{product.name}</Text>
                    <Text style={styles.productPrice}>{formatMoney(product.price)}</Text>
                    {productRequiresStock(product) ? (
                      <Text style={styles.productStock}>Stock: {productStockAvailable(product)}</Text>
                    ) : (
                      <Text style={styles.serviceNote}>No stock required</Text>
                    )}
                  </Pressable>
                );
              })}
            </View>
            {!filteredCatalog.length ? <Text style={styles.muted}>No items match your search.</Text> : null}
          </View>

          <View style={styles.card}>
            <Text style={styles.cardTitle}>Current sale</Text>
            {!cart.length ? <Text style={styles.muted}>Cart is empty.</Text> : null}
            {cart.map((line, index) => (
              <View key={`${line.service_product_id}-${index}`} style={styles.cartLine}>
                <View style={styles.cartLineInfo}>
                  <Text style={styles.productName}>{line.name}</Text>
                  <Text style={styles.muted}>
                    {formatMoney(line.unit_price)} x {line.quantity}
                  </Text>
                </View>
                <View style={styles.cartActions}>
                  <AppButton label="Less" icon="remove" variant="secondary" onPress={() => changeQty(index, -1)} />
                  <AppButton label="More" icon="add" variant="secondary" onPress={() => changeQty(index, 1)} />
                </View>
              </View>
            ))}

            <PosDiscountPanel
              discountType={discountType}
              discountValue={discountValue}
              scPwdIdNumber={scPwdIdNumber}
              onDiscountTypeChange={setDiscountType}
              onDiscountValueChange={setDiscountValue}
              onScPwdIdNumberChange={setScPwdIdNumber}
            />

            <PosCustomerLookup
              saleCustomerType={saleCustomerType}
              selectedCustomerId={selectedCustomerId}
              customers={customers}
              onSaleCustomerTypeChange={setSaleCustomerType}
              onSelectedCustomerIdChange={setSelectedCustomerId}
            />

            <PosPatientLookup patientId={selectedPatientId} onPatientIdChange={setSelectedPatientId} />

            <Text style={styles.label}>Tax rate (%)</Text>
            <TextInput style={styles.input} keyboardType="decimal-pad" value={taxRate} onChangeText={setTaxRate} />

            <PosPaymentLines
              payments={payments}
              orderTotal={totals.total}
              deviceConnected={Boolean(session.connected_device_id)}
              capturingIndex={capturingIndex}
              onAdd={addPaymentLine}
              onRemove={removePaymentLine}
              onChange={updatePaymentLine}
              onCapture={capturePaymentLine}
            />

            {cashDue > 0 ? (
              <>
                <Text style={styles.label}>Cash tendered</Text>
                <TextInput
                  style={styles.input}
                  keyboardType="decimal-pad"
                  value={amountTendered}
                  onChangeText={setAmountTendered}
                />
              </>
            ) : null}

            <View style={styles.totalRow}>
              <Text>Subtotal</Text>
              <Text>{formatMoney(totals.subtotal)}</Text>
            </View>
            {totals.discount > 0 ? (
              <View style={styles.totalRow}>
                <Text>{getDiscountLabel(discountType)}</Text>
                <Text>-{formatMoney(totals.discount)}</Text>
              </View>
            ) : null}
            {isScPwdDiscount(discountType) ? (
              <View style={styles.totalRow}>
                <Text style={styles.muted}>VAT</Text>
                <Text style={styles.muted}>Exempt (SC/PWD)</Text>
              </View>
            ) : (
              <View style={styles.totalRow}>
                <Text>Tax</Text>
                <Text>{formatMoney(totals.tax)}</Text>
              </View>
            )}
            <View style={styles.totalRow}>
              <Text style={styles.totalLabel}>Total</Text>
              <Text style={styles.totalLabel}>{formatMoney(totals.total)}</Text>
            </View>
            {cashDue > 0 && Number(amountTendered) >= cashDue ? (
              <View style={styles.totalRow}>
                <Text>Change</Text>
                <Text>{formatMoney(Number(amountTendered) - cashDue)}</Text>
              </View>
            ) : null}

            <AppButton
              label={completing ? 'Processing...' : 'Complete sale'}
              icon="check"
              loading={completing}
              disabled={!cart.length || !paymentsBalanced}
              onPress={completeSale}
            />
            <AppButton
              label={holding ? 'Saving...' : 'Put on hold'}
              icon="forward"
              variant="secondary"
              loading={holding}
              disabled={!cart.length}
              onPress={putSaleOnHold}
            />
            <AppButton
              label="Clear cart"
              icon="close"
              variant="secondary"
              onPress={() => {
                setCart([]);
                clearSaleContext();
                resetPaymentsForTotal(0);
              }}
            />

            <AppButton
              label="Close session / reconcile"
              icon="lock"
              variant="danger"
              onPress={() => setReconciliationModalOpen(true)}
            />
          </View>
        </>
      )}

      <Modal visible={salesModalOpen} animationType="slide" onRequestClose={() => setSalesModalOpen(false)}>
        <View style={styles.modal}>
          <Text style={styles.cardTitle}>Session sales</Text>
          {salesLoading ? <Text style={styles.muted}>Loading...</Text> : null}
          <ScrollView style={styles.modalScroll}>
            {sessionSales.map((sale) => (
              <View key={sale.id} style={styles.saleRow}>
                <Text style={styles.productName}>{sale.order_number}</Text>
                <Text style={styles.muted}>
                  {sale.customer_display || (sale.customer_type === 'customer' ? 'Customer' : 'Walk-in')}
                  {' · '}
                  {formatMoney(Number(sale.total))} · {sale.status}
                </Text>
                {(sale.payments || []).map((p) => (
                  <Text key={p.id} style={styles.muted}>
                    {p.payment_mode} {formatMoney(Number(p.amount))}
                  </Text>
                ))}
                <View style={styles.saleActions}>
                  <AppButton label="Receipt" icon="invoice" variant="secondary" onPress={() => openReceipt(sale)} />
                  {canManageTransactions && sale.status === 'completed' ? (
                    <>
                      <AppButton label="Return" icon="return" variant="secondary" onPress={() => openReturnSale(sale)} />
                      <AppButton label="Edit" icon="edit" variant="secondary" onPress={() => openEditSale(sale)} />
                      <AppButton label="Void" icon="delete" variant="danger" onPress={() => openVoidSale(sale)} />
                    </>
                  ) : null}
                </View>
              </View>
            ))}
            {!salesLoading && !sessionSales.length ? (
              <Text style={styles.muted}>No sales in this session yet.</Text>
            ) : null}
          </ScrollView>
          <AppButton label="Close" icon="close" variant="secondary" onPress={() => setSalesModalOpen(false)} />
        </View>
      </Modal>

      <Modal visible={reasonModalOpen} animationType="slide" onRequestClose={() => setReasonModalOpen(false)}>
        <View style={styles.modal}>
          <Text style={styles.cardTitle}>
            {reasonMode === 'void' ? `Void ${selectedSale?.order_number}?` : `Edit ${selectedSale?.order_number}`}
          </Text>
          <Text style={styles.muted}>
            {reasonMode === 'void'
              ? 'This voids the sale, refunds payments, and restores inventory. A reason is required.'
              : 'Update notes or payment references. A reason is required before saving.'}
          </Text>
          <Text style={styles.label}>Reason</Text>
          <TextInput
            style={[styles.input, styles.textarea]}
            multiline
            numberOfLines={3}
            value={reasonText}
            onChangeText={setReasonText}
            placeholder="Enter reason (required)"
          />
          {reasonMode === 'edit' ? (
            <>
              <Text style={styles.label}>Sale notes</Text>
              <TextInput
                style={[styles.input, styles.textarea]}
                multiline
                value={editNotes}
                onChangeText={setEditNotes}
              />
              {(editPayments || []).map((payment) => (
                <View key={payment.id} style={styles.editPayment}>
                  <Text style={styles.productName}>
                    {payment.payment_mode} — {formatMoney(payment.amount)}
                  </Text>
                  <TextInput
                    style={styles.input}
                    placeholder="Reference number"
                    value={payment.reference_number || ''}
                    onChangeText={(text) =>
                      setEditPayments((current) =>
                        (current || []).map((p) =>
                          p.id === payment.id ? { ...p, reference_number: text } : p,
                        ),
                      )
                    }
                  />
                  <TextInput
                    style={styles.input}
                    placeholder="Authorization code"
                    value={payment.authorization_code || ''}
                    onChangeText={(text) =>
                      setEditPayments((current) =>
                        (current || []).map((p) =>
                          p.id === payment.id ? { ...p, authorization_code: text } : p,
                        ),
                      )
                    }
                  />
                </View>
              ))}
            </>
          ) : null}
          <AppButton
            label={reasonSaving ? 'Saving...' : 'Save'}
            icon="check"
            loading={reasonSaving}
            disabled={reasonText.trim().length < 3}
            onPress={submitReasonModal}
          />
          <AppButton label="Cancel" icon="close" variant="secondary" onPress={() => setReasonModalOpen(false)} />
        </View>
      </Modal>

      <PosPrescriptionModal
        visible={prescriptionModalOpen}
        onClose={() => setPrescriptionModalOpen(false)}
        onLoaded={onPrescriptionLoaded}
      />

      <PosReceiptModal
        visible={receiptModalOpen}
        receipt={receiptData}
        clinicName={userName !== 'User' ? userName : 'Clinic'}
        onClose={() => setReceiptModalOpen(false)}
      />

      <PosReturnModal
        visible={returnModalOpen}
        sale={returnSale}
        onClose={() => setReturnModalOpen(false)}
        onReturned={async () => {
          setSuccess('Return processed.');
          await loadDashboard();
          if (salesModalOpen) await openSalesHistory();
        }}
      />

      <PosReconciliationModal
        visible={reconciliationModalOpen}
        reconciliation={reconciliation}
        onClose={() => setReconciliationModalOpen(false)}
        onSessionClosed={() => {
          setSession(null);
          setCart([]);
          clearSaleContext();
          setReconciliation(null);
          setHeldSales([]);
          setSuccess('POS session closed.');
        }}
      />

      <PosHeldSalesModal
        visible={heldSalesModalOpen}
        heldSales={heldSales}
        loading={heldSalesLoading}
        onClose={() => setHeldSalesModalOpen(false)}
        onResume={resumeHeldSale}
        onDiscard={discardHeldSale}
      />

      <Modal visible={deviceModalOpen} animationType="fade" transparent onRequestClose={() => setDeviceModalOpen(false)}>
        <View style={styles.modalOverlay}>
          <View style={styles.modalCard}>
            <Text style={styles.cardTitle}>Register payment device</Text>
            <TextInput
              style={styles.input}
              value={newDeviceName}
              onChangeText={setNewDeviceName}
              placeholder="Device name"
            />
            <AppButton label="Register" icon="add" onPress={registerDevice} />
            <AppButton label="Cancel" icon="close" variant="secondary" onPress={() => setDeviceModalOpen(false)} />
          </View>
        </View>
      </Modal>
    </ScreenLayout>
  );
}

const styles = StyleSheet.create({
  card: {
    backgroundColor: colors.surface,
    borderRadius: radii.lg,
    borderWidth: 1,
    borderColor: colors.border,
    padding: spacing.md,
    marginBottom: spacing.md,
    gap: spacing.sm,
  },
  cardTitle: { fontSize: 18, fontWeight: '700', color: colors.text },
  badge: {
    alignSelf: 'flex-start',
    backgroundColor: colors.primaryLight,
    color: colors.primaryDark,
    fontWeight: '700',
    paddingHorizontal: spacing.sm,
    paddingVertical: 4,
    borderRadius: radii.pill,
    overflow: 'hidden',
  },
  connected: { color: colors.success, fontWeight: '600' },
  actionsRow: { marginBottom: spacing.sm },
  rowActions: { flexDirection: 'row', gap: spacing.sm, flexWrap: 'wrap' },
  label: { fontSize: 14, fontWeight: '600', color: colors.text, marginTop: spacing.sm },
  input: {
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: radii.md,
    paddingHorizontal: spacing.md,
    paddingVertical: spacing.sm,
    backgroundColor: colors.surface,
    color: colors.text,
  },
  textarea: { minHeight: 80, textAlignVertical: 'top' },
  catalog: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.sm, marginTop: spacing.sm },
  product: {
    width: '47%',
    backgroundColor: colors.background,
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: radii.md,
    padding: spacing.sm,
    gap: 4,
  },
  productDisabled: { opacity: 0.5 },
  productType: { fontSize: 11, color: colors.textMuted, textTransform: 'uppercase' },
  productName: { fontSize: 15, fontWeight: '700', color: colors.text },
  productPrice: { fontSize: 14, color: colors.text },
  productStock: { fontSize: 12, color: colors.textMuted },
  serviceNote: { color: colors.success, fontSize: 12, fontWeight: '600' },
  cartLine: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    borderBottomWidth: 1,
    borderBottomColor: colors.border,
    paddingVertical: spacing.sm,
    gap: spacing.sm,
  },
  cartLineInfo: { flex: 1 },
  cartActions: { flexDirection: 'row', gap: spacing.xs },
  devicePicker: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.xs },
  deviceActions: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.xs },
  chipRow: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: spacing.xs,
    marginBottom: spacing.sm,
  },
  chip: {
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: radii.pill,
    paddingHorizontal: spacing.sm,
    paddingVertical: 6,
  },
  chipActive: { backgroundColor: colors.primary, borderColor: colors.primary },
  chipText: { color: colors.text, fontSize: 12 },
  chipTextActive: { color: '#fff', fontWeight: '700' },
  totalRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: spacing.xs },
  totalLabel: { fontSize: 18, fontWeight: '700', color: colors.text },
  muted: { color: colors.textMuted },
  error: { color: colors.danger, marginBottom: spacing.sm },
  success: { color: colors.success, marginBottom: spacing.sm },
  modal: { flex: 1, backgroundColor: colors.background, padding: spacing.lg, gap: spacing.sm },
  modalScroll: { flex: 1 },
  saleRow: {
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: radii.md,
    padding: spacing.sm,
    marginBottom: spacing.sm,
    gap: spacing.xs,
  },
  saleActions: { flexDirection: 'row', gap: spacing.xs, marginTop: spacing.xs },
  editPayment: {
    borderWidth: 1,
    borderColor: colors.border,
    borderRadius: radii.md,
    padding: spacing.sm,
    gap: spacing.xs,
    marginTop: spacing.sm,
  },
  modalOverlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.45)',
    justifyContent: 'center',
    padding: spacing.lg,
  },
  modalCard: {
    backgroundColor: colors.surface,
    borderRadius: radii.lg,
    padding: spacing.lg,
    gap: spacing.sm,
  },
});
