import React from 'react';
import { createRoot } from 'react-dom/client';
import {
  BadgeDollarSign,
  Bell,
  Boxes,
  CalendarDays,
  CalendarClock,
  CheckCircle2,
  ChevronRight,
  ClipboardList,
  CreditCard,
  Download,
  FileText,
  LayoutDashboard,
  LogOut,
  MapPin,
  PackageCheck,
  Pencil,
  Phone,
  Plus,
  RefreshCw,
  Save,
  Search,
  ShoppingBag,
  Trash2,
  Truck,
  UserPlus,
  UsersRound,
  X
} from 'lucide-react';
import './styles.css';

type Page = 'dashboard' | 'orders' | 'customers' | 'delivery' | 'catering' | 'quotation' | 'invoice' | 'products' | 'payments' | 'users';
type CrmRole = 'admin' | 'manager' | 'viewer';
type CrmUser = { id: string; name: string; email: string; role: CrmRole; createdAt: string };
type Kpis = { revenue: number; orders: number; activeOrders: number; averageOrderValue: number; customers: number };
type DashboardData = {
  mocked: boolean;
  generatedAt: string;
  kpis: Kpis;
  pipeline: Record<string, number>;
  zones: ZoneSummary[];
  productDemand: ProductDemand[];
  sources: OrderSource[];
  orders: Order[];
  customers: Customer[];
  products: Product[];
};
type OrderSource = { key: string; label: string };
type Order = {
  id: number; number: string; status: string; date: string; customer: string; phone: string;
  email: string; zone: string; source: string; sourceKey: string; payment: string; paymentMethod: string; total: number; items: number;
  deliveryCharge: number; deliveryTime: string; deliveryInstructions: string; products: OrderProduct[];
};
type OrderProduct = { id: number; productId: number; name: string; quantity: number; total: number; image: string };
type EditableProduct = { lineItemId?: number; productId: number; quantity: number };
type QuotationItem = { name: string; quantity: number; rate: number };
type OrderChanges = {
  customer: string; phone: string; email: string; status: string; deliveryZone: string;
  deliveryCharge: number; deliveryTime: string; deliveryInstructions: string;
  source: string; paymentMethod: string; paymentTitle: string; products: EditableProduct[];
};
type Customer = {
  id: number | string; name: string; email: string; orders: number; spent: number;
  city: string; phone: string; lastOrder?: string;
};
type Product = { id: number; name: string; status: string; price: number; stock: string; image: string };
type ZoneSummary = { area: string; orders: number; revenue: number };
type ProductDemand = { name: string; quantity: number; revenue: number };
type CateringSubmission = {
  id: number; submittedAt: string; isRead: boolean; status: string; name: string;
  phone: string; eventDate: string; email: string; message: string;
};

const statusLabels: Record<string, string> = {
  pending: 'Pending', processing: 'Preparing', 'on-hold': 'Payment Hold', completed: 'Completed',
  cancelled: 'Cancelled', failed: 'Failed', refunded: 'Refunded'
};
const pageTitles: Record<Page, [string, string]> = {
  dashboard: ['Operations Dashboard', 'Live WooCommerce performance and order flow.'],
  orders: ['Orders', 'Search, prioritize, and follow every order.'],
  customers: ['Customers', 'Buyer history, contact details, and lifetime value.'],
  delivery: ['Delivery', 'Track active deliveries and area performance.'],
  catering: ['Catering', 'Review catering requests submitted from the booking form.'],
  quotation: ['Create Quotation', 'Prepare and download a customer catering quotation.'],
  invoice: ['Create Invoice', 'Build and download a standalone customer invoice.'],
  products: ['Products', 'Catalog availability and recent customer demand.'],
  payments: ['Payments', 'Revenue and order volume by payment method.']
  ,users: ['Users', 'Manage CRM access and user roles.']
};

function App() {
  const [authLoading, setAuthLoading] = React.useState(true);
  const [needsSetup, setNeedsSetup] = React.useState(false);
  const [currentUser, setCurrentUser] = React.useState<CrmUser | null>(null);
  const [data, setData] = React.useState<DashboardData | null>(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState('');
  const [page, setPage] = React.useState<Page>(readPage);
  const [selectedOrder, setSelectedOrder] = React.useState<Order | null>(null);
  const [creatingOrder, setCreatingOrder] = React.useState(false);
  const [notificationsOpen, setNotificationsOpen] = React.useState(false);

  React.useEffect(() => {
    fetch('/api/auth/status')
      .then(async (response) => {
        if (!response.ok) throw new Error('Could not check CRM login status.');
        return response.json();
      })
      .then((status) => {
        setNeedsSetup(status.needsSetup);
        setCurrentUser(status.user);
      })
      .catch((statusError) => setError(statusError instanceof Error ? statusError.message : 'Could not check CRM login status.'))
      .finally(() => setAuthLoading(false));
  }, []);

  const loadDashboard = React.useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const response = await fetch('/api/dashboard');
      if (!response.ok) throw new Error(`Dashboard API failed (${response.status})`);
      setData(await response.json());
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Could not load dashboard');
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => { if (currentUser) void loadDashboard(); }, [currentUser, loadDashboard]);
  React.useEffect(() => {
    const onHashChange = () => setPage(readPage());
    window.addEventListener('hashchange', onHashChange);
    if (!window.location.hash) window.history.replaceState(null, '', '#dashboard');
    return () => window.removeEventListener('hashchange', onHashChange);
  }, []);

  const navigate = (nextPage: Page) => {
    window.location.hash = nextPage;
    setPage(nextPage);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const logout = async () => {
    await fetch('/api/auth/logout', { method: 'POST' });
    setCurrentUser(null);
    setData(null);
    setPage('dashboard');
  };

  const updateOrder = async (order: Order, changes: OrderChanges) => {
    const response = await fetch(`/api/orders/${order.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(changes)
    });
    if (!response.ok) throw new Error(await response.text());
    const updated = await response.json();
    setData((current) => current ? { ...current, orders: current.orders.map((item) => item.id === updated.id ? updated : item) } : current);
    setSelectedOrder(updated);
  };

  const createOrder = async (changes: OrderChanges) => {
    const response = await fetch('/api/orders', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(changes)
    });
    if (!response.ok) throw new Error(await response.text());
    const created = await response.json();
    setData((current) => current ? { ...current, orders: [created, ...current.orders] } : current);
    setCreatingOrder(false);
    setSelectedOrder(created);
  };

  const deleteOrder = async (order: Order) => {
    if (!window.confirm(`Move order #${order.number} to WooCommerce Trash?`)) return;
    const response = await fetch(`/api/orders/${order.id}`, { method: 'DELETE' });
    if (!response.ok) throw new Error(await response.text());
    setData((current) => current ? { ...current, orders: current.orders.filter((item) => item.id !== order.id) } : current);
    setSelectedOrder(null);
  };

  if (authLoading) return <LoadingScreen />;
  if (!currentUser) return <AuthScreen needsSetup={needsSetup} onAuthenticated={(user) => { setCurrentUser(user); setNeedsSetup(false); }} />;
  if (loading && !data) return <LoadingScreen />;

  const canManageOrders = currentUser.role !== 'viewer';
  const canDeleteOrders = currentUser.role === 'admin';

  return (
    <div className="app-shell">
      <Sidebar page={page} user={currentUser} onNavigate={navigate} onLogout={logout} />
      <main className="workspace">
        <header className="topbar">
          <div>
            <p className="eyebrow">Gravy Chawal CRM</p>
            <h1>{pageTitles[page][0]}</h1>
            <p className="page-subtitle">{pageTitles[page][1]}</p>
          </div>
          <div className="topbar-actions">
            {data?.mocked && <span className="mode-pill">Mock data</span>}
            <button className="icon-button" type="button" title="Refresh data" onClick={loadDashboard} disabled={loading}>
              <RefreshCw className={loading ? 'spinning' : ''} size={18} />
            </button>
            <button className={`icon-button notification-button ${notificationsOpen ? 'active' : ''}`} type="button" title="Notifications" onClick={() => setNotificationsOpen((open) => !open)}>
              <Bell size={18} />
              {data && data.kpis.activeOrders > 0 && <span className="notification-dot" />}
            </button>
          </div>
          {notificationsOpen && data && (
            <div className="notification-popover">
              <strong>Operations update</strong>
              <span>{data.kpis.activeOrders} active orders need attention.</span>
              <button type="button" onClick={() => { navigate('orders'); setNotificationsOpen(false); }}>
                Review orders <ChevronRight size={14} />
              </button>
            </div>
          )}
        </header>

        {error && <div className="alert">{error}</div>}
        {data && (
          <div className="page-content">
            {page === 'dashboard' && <DashboardPage data={data} onSelectOrder={setSelectedOrder} onNavigate={navigate} />}
            {page === 'orders' && <OrdersPage data={data} canManage={canManageOrders} canDelete={canDeleteOrders} onCreateOrder={() => setCreatingOrder(true)} onSelectOrder={setSelectedOrder} onDeleteOrder={deleteOrder} />}
            {page === 'customers' && <CustomersPage customers={data.customers} />}
            {page === 'delivery' && <DeliveryPage data={data} canManage={canManageOrders} canDelete={canDeleteOrders} onSelectOrder={setSelectedOrder} onDeleteOrder={deleteOrder} />}
            {page === 'catering' && <CateringPage />}
            {page === 'quotation' && <QuotationPage data={data} />}
            {page === 'invoice' && <InvoicePage data={data} />}
            {page === 'products' && <ProductsPage data={data} />}
            {page === 'payments' && <PaymentsPage orders={data.orders} canManage={canManageOrders} canDelete={canDeleteOrders} onSelectOrder={setSelectedOrder} onDeleteOrder={deleteOrder} />}
            {page === 'users' && currentUser.role === 'admin' && <UsersPage currentUser={currentUser} />}
          </div>
        )}
      </main>
      {selectedOrder && data && <OrderDrawer order={selectedOrder} data={data} canManage={canManageOrders} canDelete={canDeleteOrders} onClose={() => setSelectedOrder(null)} onSave={updateOrder} onDelete={deleteOrder} />}
      {creatingOrder && data && canManageOrders && <NewOrderDrawer data={data} onClose={() => setCreatingOrder(false)} onSave={createOrder} />}
    </div>
  );
}

function Sidebar({ page, user, onNavigate, onLogout }: { page: Page; user: CrmUser; onNavigate: (page: Page) => void; onLogout: () => Promise<void> }) {
  const items = [
    { icon: LayoutDashboard, label: 'Dashboard', page: 'dashboard' as Page },
    { icon: ClipboardList, label: 'Orders', page: 'orders' as Page },
    { icon: UsersRound, label: 'Customers', page: 'customers' as Page },
    { icon: Truck, label: 'Delivery', page: 'delivery' as Page },
    { icon: CalendarDays, label: 'Catering', page: 'catering' as Page },
    { icon: Boxes, label: 'Products', page: 'products' as Page },
    { icon: CreditCard, label: 'Payments', page: 'payments' as Page },
    ...(user.role === 'admin' ? [{ icon: UsersRound, label: 'Users', page: 'users' as Page }] : [])
  ];
  return (
    <aside className="sidebar">
      <div className="brand">
        <img
          className="brand-logo"
          src="http://localhost/gravy/wp-content/uploads/2026/01/logo1.svg"
          alt="Gravy"
        />
      </div>
      <nav>
        {items.map((item) => <React.Fragment key={item.page}>
          <button className={page === item.page || (item.page === 'catering' && ['quotation', 'invoice'].includes(page)) ? 'active' : ''} onClick={() => onNavigate(item.page)} type="button">
            <item.icon size={18} /><span>{item.label}</span>
          </button>
          {item.page === 'catering' && <div className="sidebar-subnav">
            <button className={page === 'quotation' ? 'active' : ''} onClick={() => onNavigate('quotation')} type="button"><FileText size={16} /><span>Quotation</span></button>
            <button className={page === 'invoice' ? 'active' : ''} onClick={() => onNavigate('invoice')} type="button"><BadgeDollarSign size={16} /><span>Invoice</span></button>
          </div>}
        </React.Fragment>)}
      </nav>
      <div className="sidebar-user"><div className="avatar">{initials(user.name)}</div><div><strong>{user.name}</strong><span>{roleLabel(user.role)}</span></div><button type="button" title="Log out" onClick={() => void onLogout()}><LogOut size={17} /></button></div>
      <div className="sidebar-card">
        <PackageCheck size={20} /><strong>Live store connected</strong>
        <span>WooCommerce orders and catalog data refresh securely.</span>
      </div>
    </aside>
  );
}

function DashboardPage({ data, onSelectOrder, onNavigate }: { data: DashboardData; onSelectOrder: (order: Order) => void; onNavigate: (page: Page) => void }) {
  return (
    <>
      <KpiGrid kpis={data.kpis} />
      <section className="dashboard-grid">
        <Panel title="Order Pipeline" action={`${data.orders.length} recent`}>
          <Pipeline pipeline={data.pipeline} />
        </Panel>
        <Panel title="Needs Attention" action={formatTime(data.generatedAt)}>
          <FocusList orders={data.orders} onSelect={onSelectOrder} />
        </Panel>
      </section>
      <section className="lower-grid">
        <Panel title="Top Delivery Zones" action="View delivery">
          <ZoneList zones={data.zones.slice(0, 5)} />
          <TextAction label="Open delivery page" onClick={() => onNavigate('delivery')} />
        </Panel>
        <Panel title="Product Demand" action="Recent orders">
          <ProductDemandList products={data.productDemand.slice(0, 5)} />
          <TextAction label="Open products page" onClick={() => onNavigate('products')} />
        </Panel>
        <Panel title="Recent Orders" action="Latest">
          <FocusList orders={data.orders.slice(0, 5)} onSelect={onSelectOrder} includeAll />
          <TextAction label="Open orders page" onClick={() => onNavigate('orders')} />
        </Panel>
      </section>
    </>
  );
}

function OrdersPage({ data, canManage, canDelete, onCreateOrder, onSelectOrder, onDeleteOrder }: { data: DashboardData; canManage: boolean; canDelete: boolean; onCreateOrder: () => void; onSelectOrder: (order: Order) => void; onDeleteOrder: (order: Order) => Promise<void> }) {
  const [query, setQuery] = React.useState('');
  const [status, setStatus] = React.useState('all');
  const [area, setArea] = React.useState('all');
  const [payment, setPayment] = React.useState('all');
  const [source, setSource] = React.useState('all');
  const areas = unique(data.orders.map((order) => order.zone));
  const payments = unique(data.orders.map((order) => order.payment));
  const sources = getSourceOptions(data.orders);
  const orders = data.orders.filter((order) => {
    const text = query.trim().toLowerCase();
    return (status === 'all' || order.status === status) &&
      (area === 'all' || order.zone === area) &&
      (payment === 'all' || order.payment === payment) &&
      (source === 'all' || order.sourceKey === source) &&
      (!text || [order.number, order.customer, order.phone, order.email, order.zone, order.source].some((value) => value.toLowerCase().includes(text)));
  });
  return (
    <DataSection title={`${orders.length} orders`} subtitle="Filtered from the latest WooCommerce orders.">
      {canManage && <div className="section-actions"><button className="create-order-button" type="button" onClick={onCreateOrder}><Plus size={17} /> New order</button></div>}
      <FilterBar query={query} setQuery={setQuery} placeholder="Search order, customer, phone">
        <FilterSelect value={status} onChange={setStatus} label="All statuses" options={Object.keys(data.pipeline).map((value) => [value, labelStatus(value)])} />
        <FilterSelect value={area} onChange={setArea} label="All zones" options={areas.map((value) => [value, value])} />
        <FilterSelect value={payment} onChange={setPayment} label="All payments" options={payments.map((value) => [value, value])} />
        <FilterSelect value={source} onChange={setSource} label="All sources" options={sources} />
      </FilterBar>
      <OrderTable orders={orders} canManage={canManage} canDelete={canDelete} excludeDeliveryFromTotal onSelect={onSelectOrder} onDelete={onDeleteOrder} />
    </DataSection>
  );
}

function CustomersPage({ customers }: { customers: Customer[] }) {
  const [query, setQuery] = React.useState('');
  const [value, setValue] = React.useState('all');
  const [sort, setSort] = React.useState('spent');
  const filtered = customers
    .filter((customer) => {
      const text = query.trim().toLowerCase();
      const matchesValue = value === 'all' || (value === 'repeat' && customer.orders > 1) || (value === 'vip' && customer.spent >= 10000) || (value === 'new' && customer.orders <= 1);
      return matchesValue && (!text || [customer.name, customer.email, customer.phone, customer.city].some((item) => item.toLowerCase().includes(text)));
    })
    .sort((a, b) => sort === 'orders' ? b.orders - a.orders : sort === 'name' ? a.name.localeCompare(b.name) : b.spent - a.spent);
  return (
    <>
      <MetricStrip items={[
        ['Customer profiles', String(customers.length)],
        ['Repeat buyers', String(customers.filter((customer) => customer.orders > 1).length)],
        ['Customer value', money(sum(customers.map((customer) => customer.spent)))]
      ]} />
      <DataSection title={`${filtered.length} customers`} subtitle="Registered customers and guest checkout profiles.">
        <FilterBar query={query} setQuery={setQuery} placeholder="Search name, phone, email">
          <FilterSelect value={value} onChange={setValue} label="All customers" options={[['repeat', 'Repeat buyers'], ['vip', 'PKR 10k+ value'], ['new', 'One-time buyers']]} />
          <FilterSelect value={sort} onChange={setSort} label="Sort by spend" options={[['orders', 'Sort by orders'], ['name', 'Sort by name']]} hideAll />
        </FilterBar>
        <CustomerTable customers={filtered} />
      </DataSection>
    </>
  );
}

function CateringPage() {
  const [submissions, setSubmissions] = React.useState<CateringSubmission[]>([]);
  const [selected, setSelected] = React.useState<CateringSubmission | null>(null);
  const [query, setQuery] = React.useState('');
  const [timing, setTiming] = React.useState('all');
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState('');

  React.useEffect(() => {
    fetch('/api/catering')
      .then(async (response) => {
        const result = await response.json();
        if (!response.ok) throw new Error(result.error || 'Could not load catering requests.');
        setSubmissions(result);
      })
      .catch((loadError) => setError(loadError instanceof Error ? loadError.message : 'Could not load catering requests.'))
      .finally(() => setLoading(false));
  }, []);

  const today = new Date().toISOString().slice(0, 10);
  const filtered = submissions.filter((submission) => {
    const text = query.trim().toLowerCase();
    const matchesText = !text || [submission.name, submission.phone, submission.email, submission.message].some((value) => value.toLowerCase().includes(text));
    const matchesTiming = timing === 'all' || (timing === 'upcoming' ? submission.eventDate >= today : submission.eventDate < today);
    return matchesText && matchesTiming;
  });
  const upcoming = submissions.filter((submission) => submission.eventDate >= today);

  return <>
    <MetricStrip items={[
      ['Total requests', String(submissions.length)],
      ['Upcoming events', String(upcoming.length)],
      ['Unread', String(submissions.filter((submission) => !submission.isRead).length)]
    ]} />
    <DataSection title={`${filtered.length} catering requests`} subtitle="Submissions from the Book Your Catering form.">
      <FilterBar query={query} setQuery={setQuery} placeholder="Search name, phone, email">
        <FilterSelect value={timing} onChange={setTiming} label="All event dates" options={[['upcoming', 'Upcoming'], ['past', 'Past events']]} />
      </FilterBar>
      {error && <div className="alert">{error}</div>}
      {loading ? <p className="empty-state">Loading catering requests...</p> : <CateringTable submissions={filtered} onSelect={setSelected} />}
    </DataSection>
    {selected && <CateringDrawer submission={selected} onClose={() => setSelected(null)} />}
  </>;
}

function CateringTable({ submissions, onSelect }: { submissions: CateringSubmission[]; onSelect: (submission: CateringSubmission) => void }) {
  return <div className="table-wrap"><table><thead><tr><th>Submitted</th><th>Customer</th><th>Contact</th><th>Event Date</th><th>Message</th><th>Status</th></tr></thead><tbody>{submissions.map((submission) => (
    <tr className="order-row" key={submission.id} onClick={() => onSelect(submission)}>
      <td><strong>#{submission.id}</strong><span>{formatDate(submission.submittedAt)}</span></td>
      <td><strong>{submission.name || 'Not provided'}</strong></td>
      <td><strong>{submission.phone || 'No phone'}</strong><span>{submission.email || 'No email'}</span></td>
      <td><strong>{formatEventDate(submission.eventDate)}</strong></td>
      <td className="message-cell">{submission.message || 'No message'}</td>
      <td><span className={`request-status ${submission.isRead ? 'read' : 'new'}`}>{submission.isRead ? 'Read' : 'New'}</span></td>
    </tr>
  ))}</tbody></table>{!submissions.length && <p className="empty-state">No catering requests match the current filters.</p>}</div>;
}

function CateringDrawer({ submission, onClose }: { submission: CateringSubmission; onClose: () => void }) {
  React.useEffect(() => {
    const handleKey = (event: KeyboardEvent) => event.key === 'Escape' && onClose();
    window.addEventListener('keydown', handleKey);
    return () => window.removeEventListener('keydown', handleKey);
  }, [onClose]);

  return <div className="drawer-backdrop" role="presentation" onMouseDown={onClose}><aside className="order-drawer" role="dialog" aria-modal="true" aria-label={`Catering request ${submission.id}`} onMouseDown={(event) => event.stopPropagation()}>
    <div className="drawer-head"><div><span>Catering request #{submission.id}</span><h2>{submission.name}</h2></div><button className="icon-button" type="button" title="Close catering request" onClick={onClose}><X size={18} /></button></div>
    <span className={`request-status ${submission.isRead ? 'read' : 'new'}`}>{submission.isRead ? 'Read' : 'New request'}</span>
    <div className="catering-event-card"><span>Event date</span><strong>{formatEventDate(submission.eventDate)}</strong></div>
    <dl className="detail-list">
      <div><dt>Submitted</dt><dd>{formatDate(submission.submittedAt)}</dd></div>
      <div><dt>Phone</dt><dd>{submission.phone || 'Not provided'}</dd></div>
      <div className="detail-wide"><dt>Email</dt><dd>{submission.email || 'Not provided'}</dd></div>
      <div className="detail-wide"><dt>Message</dt><dd className="catering-message">{submission.message || 'No message provided'}</dd></div>
    </dl>
    {submission.phone && <a className="primary-action" href={`tel:${submission.phone}`}><Phone size={16} /> Call customer</a>}
    {submission.email && <a className="secondary-action" href={`mailto:${submission.email}`}>Email customer</a>}
  </aside></div>;
}

function QuotationPage({ data }: { data: DashboardData }) {
  return <DocumentBuilder data={data} kind="quotation" />;
}

function DocumentBuilder({ data, kind }: { data: DashboardData; kind: 'quotation' | 'invoice' }) {
  const isInvoice = kind === 'invoice';
  const documentLabel = isInvoice ? 'Invoice' : 'Quotation';
  const today = new Date().toISOString().slice(0, 10);
  const [customerId, setCustomerId] = React.useState('');
  const [customer, setCustomer] = React.useState('');
  const [quoteNumber, setQuoteNumber] = React.useState(() => `${isInvoice ? 'INV' : 'QT'}-${String(Date.now()).slice(-6)}`);
  const [quoteDate, setQuoteDate] = React.useState(today);
  const [expiryDate, setExpiryDate] = React.useState('');
  const [deliveryCharge, setDeliveryCharge] = React.useState(0);
  const [items, setItems] = React.useState<QuotationItem[]>([{ name: '', quantity: 1, rate: 0 }]);
  const [notes, setNotes] = React.useState('Looking forward to your business.');
  const [termsVisible, setTermsVisible] = React.useState(false);
  const [terms, setTerms] = React.useState('');
  const [generating, setGenerating] = React.useState(false);
  const [error, setError] = React.useState('');

  const selectCustomer = (value: string) => {
    setCustomerId(value);
    const selected = data.customers.find((item) => String(item.id) === value);
    setCustomer(selected?.name || '');
  };
  const updateItem = (index: number, change: Partial<QuotationItem>) => {
    setItems((current) => current.map((item, itemIndex) => itemIndex === index ? { ...item, ...change } : item));
  };
  const itemAmount = (item: QuotationItem) => item.quantity * item.rate;
  const subtotal = sum(items.map((item) => item.quantity * item.rate));
  const total = subtotal + deliveryCharge;

  const generate = async () => {
    if (!customer.trim()) return setError('Customer name is required.');
    if (!quoteNumber.trim()) return setError(`${documentLabel} number is required.`);
    if (!items.length) return setError('Add at least one item.');
    if (items.some((item) => !item.name.trim())) return setError('Enter details for every item.');
    setGenerating(true);
    setError('');
    try {
      await downloadDocument({ kind, customer, documentNumber: quoteNumber, documentDate: quoteDate, expiryDate: isInvoice ? '' : expiryDate, deliveryCharge, items, notes, terms: termsVisible ? terms : '' });
    } catch (generateError) {
      setError(generateError instanceof Error ? generateError.message : `Could not generate ${kind}.`);
    } finally {
      setGenerating(false);
    }
  };

  return <section className="panel quotation-panel">
    <div className="quotation-customer-row">
      <label><span>Customer Name*</span><select value={customerId} onChange={(event) => selectCustomer(event.target.value)}><option value="">Select or add a customer</option>{data.customers.map((item) => <option value={String(item.id)} key={item.id}>{item.name} - {item.phone || item.email}</option>)}</select></label>
      <label><span>Manual customer</span><input value={customer} placeholder="Customer name" onChange={(event) => { setCustomer(event.target.value); setCustomerId(''); }} /></label>
    </div>
    <div className={`quotation-meta ${isInvoice ? 'invoice-meta' : ''}`}>
      <label><span>{documentLabel} #*</span><input value={quoteNumber} onChange={(event) => setQuoteNumber(event.target.value)} /></label>
      <label><span>{documentLabel} Date*</span><input type="date" value={quoteDate} onChange={(event) => setQuoteDate(event.target.value)} /></label>
      {!isInvoice && <label><span>Expiry Date</span><input type="date" min={quoteDate} value={expiryDate} onChange={(event) => setExpiryDate(event.target.value)} /></label>}
    </div>

    <div className="quotation-items">
      <div className="quotation-items-title">Item Table</div>
      <div className="quotation-item-head"><span>Item details</span><span>Quantity</span><span>Rate</span><span>Amount</span><span /></div>
      {items.map((item, index) => <div className="quotation-item-row" key={index}>
        <input aria-label="Item details" placeholder="Type item details" value={item.name} onChange={(event) => updateItem(index, { name: event.target.value })} />
        <input aria-label="Quantity" type="number" min="1" value={item.quantity} onChange={(event) => updateItem(index, { quantity: Math.max(1, Number(event.target.value)) })} />
        <input aria-label="Rate" type="number" min="0" step="1" value={item.rate} onChange={(event) => updateItem(index, { rate: Math.max(0, Number(event.target.value)) })} />
        <strong>{money(itemAmount(item))}</strong>
        <button type="button" title="Remove row" disabled={items.length === 1} onClick={() => setItems((current) => current.filter((_, itemIndex) => itemIndex !== index))}><Trash2 size={15} /></button>
      </div>)}
    </div>
    <button className="quotation-add-row" type="button" onClick={() => setItems((current) => [...current, { name: '', quantity: 1, rate: 0 }])}><Plus size={15} /> Add New Row</button>

    <div className="quotation-bottom">
      <div className="quotation-notes">
        <label><span>Customer Notes</span><textarea value={notes} onChange={(event) => setNotes(event.target.value)} /></label>
        <button type="button" onClick={() => setTermsVisible((visible) => !visible)}><Plus size={15} /> {termsVisible ? 'Remove Terms and conditions' : 'Add Terms and conditions'}</button>
        {termsVisible && <label><span>Terms and conditions</span><textarea value={terms} placeholder="Enter payment, validity, or service terms" onChange={(event) => setTerms(event.target.value)} /></label>}
      </div>
      <div className="quotation-summary">
        <div><span>Subtotal (PKR)</span><strong>{money(subtotal)}</strong></div>
        <label className="quotation-delivery"><span>Delivery charges</span><input aria-label="Delivery charges" type="number" min="0" step="1" value={deliveryCharge} onChange={(event) => setDeliveryCharge(Math.max(0, Number(event.target.value)))} /></label>
        <div className="quotation-total"><span>Total (PKR)</span><strong>{money(total)}</strong></div>
        {error && <p className="form-error">{error}</p>}
        <button className="primary-action button-reset" type="button" disabled={generating} onClick={() => void generate()}><Download size={16} /> {generating ? 'Generating...' : `Download ${kind} PDF`}</button>
      </div>
    </div>
  </section>;
}

function InvoicePage({ data }: { data: DashboardData }) {
  return <DocumentBuilder data={data} kind="invoice" />;
}

function DeliveryPage({ data, canManage, canDelete, onSelectOrder, onDeleteOrder }: { data: DashboardData; canManage: boolean; canDelete: boolean; onSelectOrder: (order: Order) => void; onDeleteOrder: (order: Order) => Promise<void> }) {
  const [area, setArea] = React.useState('all');
  const [status, setStatus] = React.useState('active');
  const activeStatuses = ['pending', 'on-hold', 'processing'];
  const orders = data.orders.filter((order) =>
    (area === 'all' || order.zone === area) &&
    (status === 'all' || (status === 'active' ? activeStatuses.includes(order.status) : order.status === status))
  );
  const activeRevenue = sum(orders.map((order) => order.total));
  return (
    <>
      <MetricStrip items={[
        ['Active deliveries', String(data.orders.filter((order) => activeStatuses.includes(order.status)).length)],
        ['Delivery zones', String(data.zones.length)],
        ['Filtered value', money(activeRevenue)]
      ]} />
      <section className="split-page">
        <DataSection title="Delivery queue" subtitle={`${orders.length} orders in this view.`}>
          <FilterBar>
            <FilterSelect value={status} onChange={setStatus} label="Active orders" options={[['all', 'All statuses'], ['pending', 'Pending'], ['on-hold', 'Payment hold'], ['processing', 'Preparing']]} hideAll />
            <FilterSelect value={area} onChange={setArea} label="All zones" options={data.zones.map((zone) => [zone.area, zone.area])} />
          </FilterBar>
          <OrderTable orders={orders} canManage={canManage} canDelete={canDelete} onSelect={onSelectOrder} onDelete={onDeleteOrder} compact />
        </DataSection>
        <Panel title="Zone Performance" action={`${data.zones.length} zones`}>
          <ZoneList zones={data.zones} />
        </Panel>
      </section>
    </>
  );
}

function ProductsPage({ data }: { data: DashboardData }) {
  const [query, setQuery] = React.useState('');
  const [stock, setStock] = React.useState('all');
  const [status, setStatus] = React.useState('all');
  const demand = new Map(data.productDemand.map((item) => [item.name.toLowerCase(), item]));
  const products = data.products.filter((product) => {
    const text = query.trim().toLowerCase();
    return (stock === 'all' || product.stock === stock) && (status === 'all' || product.status === status) &&
      (!text || product.name.toLowerCase().includes(text));
  });
  return (
    <>
      <MetricStrip items={[
        ['Catalog products', String(data.products.length)],
        ['In stock', String(data.products.filter((product) => product.stock === 'instock').length)],
        ['Units ordered', String(sum(data.productDemand.map((product) => product.quantity)))]
      ]} />
      <DataSection title={`${products.length} products`} subtitle="Live WooCommerce catalog with recent demand.">
        <FilterBar query={query} setQuery={setQuery} placeholder="Search products">
          <FilterSelect value={stock} onChange={setStock} label="All stock" options={[['instock', 'In stock'], ['outofstock', 'Out of stock'], ['onbackorder', 'On backorder']]} />
          <FilterSelect value={status} onChange={setStatus} label="All visibility" options={[['publish', 'Published'], ['draft', 'Draft'], ['private', 'Private']]} />
        </FilterBar>
        <ProductGrid products={products} demand={demand} />
      </DataSection>
    </>
  );
}

function PaymentsPage({ orders, canManage, canDelete, onSelectOrder, onDeleteOrder }: { orders: Order[]; canManage: boolean; canDelete: boolean; onSelectOrder: (order: Order) => void; onDeleteOrder: (order: Order) => Promise<void> }) {
  const [method, setMethod] = React.useState('all');
  const [status, setStatus] = React.useState('all');
  const methods = unique(orders.map((order) => order.payment));
  const filtered = orders.filter((order) => (method === 'all' || order.payment === method) && (status === 'all' || order.status === status));
  const summaries = methods.map((name) => {
    const methodOrders = orders.filter((order) => order.payment === name);
    return { name, orders: methodOrders.length, revenue: sum(methodOrders.filter(isPaidOrder).map((order) => order.total)) };
  }).sort((a, b) => b.revenue - a.revenue);
  return (
    <>
      <MetricStrip items={[
        ['Captured revenue', money(sum(orders.filter(isPaidOrder).map((order) => order.total)))],
        ['Payment methods', String(methods.length)],
        ['Filtered orders', String(filtered.length)]
      ]} />
      <section className="payments-grid">
        <Panel title="Payment Methods" action="Revenue">
          <PaymentMethods methods={summaries} selected={method} onSelect={setMethod} />
        </Panel>
        <DataSection title="Payment orders" subtitle={`${filtered.length} matching orders.`}>
          <FilterBar>
            <FilterSelect value={method} onChange={setMethod} label="All methods" options={methods.map((value) => [value, value])} />
            <FilterSelect value={status} onChange={setStatus} label="All statuses" options={unique(orders.map((order) => order.status)).map((value) => [value, labelStatus(value)])} />
          </FilterBar>
          <OrderTable orders={filtered} canManage={canManage} canDelete={canDelete} onSelect={onSelectOrder} onDelete={onDeleteOrder} compact />
        </DataSection>
      </section>
    </>
  );
}

function KpiGrid({ kpis }: { kpis: Kpis }) {
  const cards = [
    { label: '30-day revenue', value: money(kpis.revenue), icon: BadgeDollarSign, tone: 'green' },
    { label: '30-day orders', value: String(kpis.orders), icon: ShoppingBag, tone: 'red' },
    { label: 'Active orders', value: String(kpis.activeOrders), icon: CalendarClock, tone: 'amber' },
    { label: 'Average order', value: money(kpis.averageOrderValue), icon: CheckCircle2, tone: 'blue' },
    { label: 'Customers', value: String(kpis.customers), icon: UsersRound, tone: 'neutral' }
  ];
  return <section className="kpi-grid">{cards.map((card) => (
    <article className={`kpi-card ${card.tone}`} key={card.label}>
      <div className="kpi-icon"><card.icon size={19} /></div><span>{card.label}</span><strong>{card.value}</strong>
    </article>
  ))}</section>;
}

function MetricStrip({ items }: { items: [string, string][] }) {
  return <section className="metric-strip">{items.map(([label, value]) => <article key={label}><span>{label}</span><strong>{value}</strong></article>)}</section>;
}

function Panel({ title, action, children, className = '' }: { title: string; action?: string; children: React.ReactNode; className?: string }) {
  return <section className={`panel ${className}`}><div className="panel-head"><h2>{title}</h2>{action && <span>{action}</span>}</div>{children}</section>;
}

function DataSection({ title, subtitle, children }: { title: string; subtitle: string; children: React.ReactNode }) {
  return <section className="orders-section data-section"><div className="section-head"><div><h2>{title}</h2><p>{subtitle}</p></div></div>{children}</section>;
}

function FilterBar({ query, setQuery, placeholder, children }: { query?: string; setQuery?: (value: string) => void; placeholder?: string; children: React.ReactNode }) {
  return <div className="filter-bar">{setQuery && <label className="search-box"><Search size={16} /><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder={placeholder} /></label>}<div className="filter-selects">{children}</div></div>;
}

function FilterSelect({ value, onChange, label, options, hideAll = false }: { value: string; onChange: (value: string) => void; label: string; options: string[][]; hideAll?: boolean }) {
  return <select value={value} onChange={(event) => onChange(event.target.value)}>{!hideAll && <option value="all">{label}</option>}{hideAll && <option value={value}>{label}</option>}{options.map(([optionValue, optionLabel]) => <option key={`${optionValue}-${optionLabel}`} value={optionValue}>{optionLabel}</option>)}</select>;
}

function Pipeline({ pipeline }: { pipeline: Record<string, number> }) {
  const total = Object.values(pipeline).reduce((sumValue, value) => sumValue + value, 0) || 1;
  return <div className="pipeline-list">{Object.keys(pipeline).map((key) => (
    <div className="pipeline-row" key={key}><div><span className={`status-dot ${key}`} /><strong>{labelStatus(key)}</strong><small>{pipeline[key]} orders</small></div><div className="pipeline-bar"><span style={{ width: `${Math.max(8, pipeline[key] / total * 100)}%` }} /></div></div>
  ))}</div>;
}

function FocusList({ orders, onSelect, includeAll = false }: { orders: Order[]; onSelect: (order: Order) => void; includeAll?: boolean }) {
  const focus = (includeAll ? orders : orders.filter((order) => ['pending', 'on-hold', 'processing'].includes(order.status))).slice(0, 5);
  if (!focus.length) return <p className="empty-state">No active orders need attention.</p>;
  return <div className="focus-list">{focus.map((order) => (
    <button className="focus-row" key={order.id} type="button" onClick={() => onSelect(order)}>
      <div className="focus-icon">{order.status === 'processing' ? <Truck size={16} /> : <CalendarClock size={16} />}</div>
      <div><strong>#{order.number} - {order.customer}</strong><span>{order.zone} - {money(order.total)}</span></div><ChevronRight size={16} />
    </button>
  ))}</div>;
}

function OrderTable({ orders, onSelect, onDelete, canManage = true, canDelete = true, compact = false, excludeDeliveryFromTotal = false }: { orders: Order[]; onSelect: (order: Order) => void; onDelete: (order: Order) => Promise<void>; canManage?: boolean; canDelete?: boolean; compact?: boolean; excludeDeliveryFromTotal?: boolean }) {
  return <div className="table-wrap"><table className={compact ? 'compact-table' : ''}><thead><tr><th>Order</th><th>Customer</th><th>Delivery Zone</th><th>Source</th>{!compact && <><th>Payment</th><th>Delivery Charges</th></>}<th>{excludeDeliveryFromTotal ? 'Total (excl. delivery)' : 'Total'}</th><th>Status</th><th>Actions</th></tr></thead><tbody>{orders.map((order) => (
    <tr className="order-row" key={order.id} onClick={() => onSelect(order)}>
      <td><strong>#{order.number}</strong><span>{formatDate(order.date)}</span></td>
      <td><strong>{order.customer}</strong><span className="inline-muted"><Phone size={12} /> {order.phone || 'No phone'}</span></td>
      <td><span className="inline-muted"><MapPin size={12} /> {order.zone}</span></td>
      <td>{order.source}</td>
      {!compact && <><td>{order.payment}</td><td>{money(order.deliveryCharge)}</td></>}<td><strong>{money(excludeDeliveryFromTotal ? orderSubtotal(order) : order.total)}</strong></td><td><StatusPill status={order.status} /></td>
      <td><div className="row-actions">{canManage && <button type="button" title="Edit order" onClick={(event) => { event.stopPropagation(); onSelect(order); }}><Pencil size={15} /></button>}<button type="button" title="Download invoice PDF" onClick={(event) => { event.stopPropagation(); void downloadInvoice(order); }}><Download size={15} /></button>{canDelete && <button className="danger" type="button" title="Delete order" onClick={(event) => { event.stopPropagation(); void onDelete(order); }}><Trash2 size={15} /></button>}</div></td>
    </tr>
  ))}</tbody></table>{!orders.length && <p className="empty-state">No records match the current filters.</p>}</div>;
}

function CustomerTable({ customers }: { customers: Customer[] }) {
  return <div className="table-wrap"><table><thead><tr><th>Customer</th><th>Contact</th><th>City</th><th>Orders</th><th>Lifetime value</th><th>Last order</th></tr></thead><tbody>{customers.map((customer) => (
    <tr key={customer.id}><td><div className="table-person"><div className="avatar">{initials(customer.name)}</div><strong>{customer.name}</strong></div></td><td><strong>{customer.phone || 'No phone'}</strong><span>{customer.email || 'No email'}</span></td><td>{customer.city}</td><td>{customer.orders}</td><td><strong>{money(customer.spent)}</strong></td><td>{customer.lastOrder ? formatDate(customer.lastOrder) : 'Not available'}</td></tr>
  ))}</tbody></table>{!customers.length && <p className="empty-state">No customers match the current filters.</p>}</div>;
}

function ProductGrid({ products, demand }: { products: Product[]; demand: Map<string, ProductDemand> }) {
  return <div className="product-grid">{products.map((product) => {
    const sales = demand.get(product.name.toLowerCase());
    return <article className="product-card" key={product.id}>
      <div className="product-image">{product.image ? <img src={product.image} alt="" /> : <ShoppingBag size={24} />}</div>
      <div className="product-info"><span className={`stock-label ${product.stock}`}>{stockLabel(product.stock)}</span><h3>{product.name}</h3><strong>{money(product.price)}</strong><small>{sales ? `${sales.quantity} ordered - ${money(sales.revenue)}` : 'No recent demand'}</small></div>
    </article>;
  })}</div>;
}

function ZoneList({ zones }: { zones: ZoneSummary[] }) {
  const max = Math.max(...zones.map((zone) => zone.orders), 1);
  return <div className="rank-list">{zones.map((zone) => <article key={zone.area}><div><strong>{zone.area}</strong><span>{zone.orders} orders - {money(zone.revenue)}</span></div><div className="mini-meter"><span style={{ width: `${zone.orders / max * 100}%` }} /></div></article>)}</div>;
}

function ProductDemandList({ products }: { products: ProductDemand[] }) {
  return <div className="rank-list">{products.map((product) => <article key={product.name}><div><strong>{product.name}</strong><span>{product.quantity} sold - {money(product.revenue)}</span></div><ShoppingBag size={16} /></article>)}</div>;
}

function PaymentMethods({ methods, selected, onSelect }: { methods: { name: string; orders: number; revenue: number }[]; selected: string; onSelect: (method: string) => void }) {
  const max = Math.max(...methods.map((method) => method.revenue), 1);
  return <div className="payment-list"><button className={selected === 'all' ? 'active' : ''} onClick={() => onSelect('all')} type="button"><CreditCard size={18} /><span><strong>All methods</strong><small>Show every payment</small></span></button>{methods.map((method) => (
    <button className={selected === method.name ? 'active' : ''} key={method.name} onClick={() => onSelect(method.name)} type="button"><CreditCard size={18} /><span><strong>{method.name}</strong><small>{method.orders} orders - {money(method.revenue)}</small><i style={{ width: `${method.revenue / max * 100}%` }} /></span></button>
  ))}</div>;
}

function TextAction({ label, onClick }: { label: string; onClick: () => void }) {
  return <button className="text-action" type="button" onClick={onClick}>{label}<ChevronRight size={15} /></button>;
}

function StatusPill({ status }: { status: string }) { return <span className={`status-pill ${status}`}>{labelStatus(status)}</span>; }

function OrderDrawer({
  order,
  data,
  canManage,
  canDelete,
  onClose,
  onSave,
  onDelete
}: {
  order: Order;
  data: DashboardData;
  canManage: boolean;
  canDelete: boolean;
  onClose: () => void;
  onSave: (order: Order, changes: OrderChanges) => Promise<void>;
  onDelete: (order: Order) => Promise<void>;
}) {
  const [editing, setEditing] = React.useState(false);

  React.useEffect(() => {
    const handleKey = (event: KeyboardEvent) => event.key === 'Escape' && onClose();
    window.addEventListener('keydown', handleKey);
    return () => window.removeEventListener('keydown', handleKey);
  }, [onClose]);

  return <div className="drawer-backdrop" role="presentation" onMouseDown={onClose}><aside className="order-drawer" role="dialog" aria-modal="true" aria-label={`Order ${order.number}`} onMouseDown={(event) => event.stopPropagation()}>
    <div className="drawer-head"><div><span>Order #{order.number}</span><h2>{order.customer}</h2></div><div className="drawer-actions"><button className="icon-button" type="button" title="Download invoice PDF" onClick={() => void downloadInvoice(order)}><Download size={18} /></button>{canManage && <button className="icon-button" type="button" title="Edit order" onClick={() => setEditing((value) => !value)}><Pencil size={18} /></button>}{canDelete && <button className="icon-button danger-button" type="button" title="Delete order" onClick={() => void onDelete(order)}><Trash2 size={18} /></button>}<button className="icon-button" type="button" title="Close order details" onClick={onClose}><X size={18} /></button></div></div>
    <StatusPill status={order.status} /><div className="order-total"><span>Order total</span><strong>{money(order.total)}</strong></div>
    {editing && <OrderForm data={data} order={order} submitLabel="Save changes" onSubmit={async (changes) => { await onSave(order, changes); setEditing(false); }} />}
    <dl className="detail-list"><div><dt>Placed</dt><dd>{formatDate(order.date)}</dd></div><div><dt>Source</dt><dd>{order.source}</dd></div><div><dt>Items</dt><dd>{order.items}</dd></div><div><dt>Delivery Zone</dt><dd>{order.zone}</dd></div><div><dt>Delivery Time</dt><dd>{formatDeliveryTime(order.deliveryTime)}</dd></div><div><dt>Delivery Charges</dt><dd>{money(order.deliveryCharge)}</dd></div><div><dt>Payment</dt><dd>{order.payment}</dd></div><div><dt>Phone</dt><dd>{order.phone || 'Not provided'}</dd></div><div><dt>Email</dt><dd>{order.email || 'Not provided'}</dd></div><div className="detail-wide"><dt>Delivery Instructions</dt><dd>{order.deliveryInstructions || 'Not provided'}</dd></div></dl>
    <section className="order-products"><h3>Products</h3>{order.products.map((product) => <article key={product.id}><div className="order-product-image">{product.image ? <img src={product.image} alt="" /> : <ShoppingBag size={18} />}</div><div><strong>{product.name}</strong><span>Qty {product.quantity}</span></div><strong>{money(product.total)}</strong></article>)}</section>
    <button className="secondary-action button-reset" type="button" onClick={() => void downloadInvoice(order)}><Download size={16} /> Download invoice PDF</button>
    {order.phone && <a className="primary-action" href={`tel:${order.phone}`}><Phone size={16} /> Call customer</a>}
  </aside></div>;
}

function NewOrderDrawer({ data, onClose, onSave }: { data: DashboardData; onClose: () => void; onSave: (changes: OrderChanges) => Promise<void> }) {
  React.useEffect(() => {
    const handleKey = (event: KeyboardEvent) => event.key === 'Escape' && onClose();
    window.addEventListener('keydown', handleKey);
    return () => window.removeEventListener('keydown', handleKey);
  }, [onClose]);

  return <div className="drawer-backdrop" role="presentation" onMouseDown={onClose}><aside className="order-drawer" role="dialog" aria-modal="true" aria-label="Create new order" onMouseDown={(event) => event.stopPropagation()}>
    <div className="drawer-head"><div><span>Manual entry</span><h2>New order</h2></div><button className="icon-button" type="button" title="Close new order" onClick={onClose}><X size={18} /></button></div>
    <OrderForm data={data} submitLabel="Create order" onSubmit={onSave} />
  </aside></div>;
}

function OrderForm({ data, order, submitLabel, onSubmit }: { data: DashboardData; order?: Order; submitLabel: string; onSubmit: (changes: OrderChanges) => Promise<void> }) {
  const paymentOptions = getPaymentOptions(data.orders);
  const [sourceOptions, setSourceOptions] = React.useState<OrderSource[]>(() => {
    const options = [...(data.sources || [])];
    if (order?.sourceKey && !options.some((option) => option.key === order.sourceKey)) {
      options.push({ key: order.sourceKey, label: order.source });
    }
    return options;
  });
  const [customer, setCustomer] = React.useState(order?.customer || '');
  const [phone, setPhone] = React.useState(order?.phone || '');
  const [email, setEmail] = React.useState(order?.email || '');
  const [status, setStatus] = React.useState(order?.status || 'processing');
  const [deliveryZone, setDeliveryZone] = React.useState(order?.zone === 'Not selected' ? '' : order?.zone || '');
  const [deliveryCharge, setDeliveryCharge] = React.useState(order?.deliveryCharge || 0);
  const [deliveryTime, setDeliveryTime] = React.useState(toDateTimeLocal(order?.deliveryTime || ''));
  const [deliveryInstructions, setDeliveryInstructions] = React.useState(order?.deliveryInstructions || '');
  const [source, setSource] = React.useState(order?.sourceKey || 'admin');
  const [paymentMethod, setPaymentMethod] = React.useState(order?.paymentMethod || paymentOptions[0]?.[0] || 'cod');
  const [products, setProducts] = React.useState<EditableProduct[]>(
    order?.products.map((product) => ({ lineItemId: product.id, productId: product.productId, quantity: product.quantity })) ||
    (data.products[0] ? [{ productId: data.products[0].id, quantity: 1 }] : [])
  );
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState('');
  const [managingSources, setManagingSources] = React.useState(false);

  const setProduct = (index: number, change: Partial<EditableProduct>) => {
    setProducts((current) => current.map((item, itemIndex) => itemIndex === index ? { ...item, ...change } : item));
  };

  const save = async () => {
    if (!customer.trim()) return setError('Customer name is required.');
    if (!products.length) return setError('Add at least one product.');
    setSaving(true);
    setError('');
    try {
      const paymentTitle = paymentOptions.find(([value]) => value === paymentMethod)?.[1] || paymentMethod;
      await onSubmit({ customer, phone, email, status, deliveryZone, deliveryCharge, deliveryTime, deliveryInstructions, source, paymentMethod, paymentTitle, products });
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : 'Could not save order');
    } finally {
      setSaving(false);
    }
  };

  return <div className="edit-order-form order-entry-form">
    <div className="form-grid">
      <label><span>Customer name</span><input value={customer} onChange={(event) => setCustomer(event.target.value)} /></label>
      <label><span>Phone</span><input value={phone} onChange={(event) => setPhone(event.target.value)} /></label>
    </div>
    <label><span>Email</span><input type="email" value={email} onChange={(event) => setEmail(event.target.value)} /></label>
    <div className="form-grid">
      <label><span>Status</span><select value={status} onChange={(event) => setStatus(event.target.value)}>{Object.keys(statusLabels).map((value) => <option key={value} value={value}>{labelStatus(value)}</option>)}</select></label>
      <label><span className="field-label-action">Source <button type="button" onClick={() => setManagingSources((value) => !value)}>{managingSources ? 'Done' : 'Manage'}</button></span><select value={source} onChange={(event) => setSource(event.target.value)}>{sourceOptions.map((option) => <option key={option.key} value={option.key}>{option.label}</option>)}</select></label>
    </div>
    {managingSources && <SourceManager sources={sourceOptions} selectedSource={source} onChange={(nextSources) => {
      setSourceOptions(nextSources);
      if (!nextSources.some((option) => option.key === source)) setSource(nextSources[0]?.key || '');
    }} />}
    <div className="form-grid">
      <label><span>Delivery Zone</span><input list="delivery-zones" value={deliveryZone} onChange={(event) => setDeliveryZone(event.target.value)} /><datalist id="delivery-zones">{unique(data.zones.map((zone) => zone.area).filter((area) => area !== 'Not selected')).map((area) => <option key={area} value={area} />)}</datalist></label>
      <label><span>Delivery Charges</span><input type="number" min="0" step="1" value={deliveryCharge} onChange={(event) => setDeliveryCharge(Math.max(0, Number(event.target.value)))} /></label>
    </div>
    <label><span>Delivery Time</span><input type="datetime-local" step="1800" value={deliveryTime} onChange={(event) => setDeliveryTime(event.target.value)} /></label>
    <label><span>Delivery Instructions</span><textarea rows={3} value={deliveryInstructions} onChange={(event) => setDeliveryInstructions(event.target.value)} placeholder="Gate, landmark, contact, or preparation notes" /></label>
    <label><span>Payment option</span><select value={paymentMethod} onChange={(event) => setPaymentMethod(event.target.value)}>{paymentOptions.map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
    <div className="product-editor">
      <div className="product-editor-head"><span>Products</span><button type="button" onClick={() => data.products[0] && setProducts((current) => [...current, { productId: data.products[0].id, quantity: 1 }])}><Plus size={14} /> Add product</button></div>
      {products.map((item, index) => <div className="product-editor-row" key={`${item.lineItemId || 'new'}-${index}`}>
        <select value={item.productId} onChange={(event) => setProduct(index, { productId: Number(event.target.value), lineItemId: undefined })}>{data.products.map((product) => <option key={product.id} value={product.id}>{product.name} - {money(product.price)}</option>)}</select>
        <input aria-label="Quantity" type="number" min="1" value={item.quantity} onChange={(event) => setProduct(index, { quantity: Math.max(1, Number(event.target.value)) })} />
        <button className="remove-product" type="button" title="Remove product" onClick={() => setProducts((current) => current.filter((_, itemIndex) => itemIndex !== index))}><Trash2 size={15} /></button>
      </div>)}
    </div>
    {error && <p className="form-error">{error}</p>}
    <button className="primary-action button-reset" type="button" disabled={saving} onClick={() => void save()}><Save size={16} /> {saving ? 'Saving...' : submitLabel}</button>
  </div>;
}

function getSourceOptions(orders: Order[]): [string, string][] {
  const options = new Map<string, string>();
  orders.forEach((order) => order.sourceKey && options.set(order.sourceKey, order.source));
  return Array.from(options.entries()).sort((a, b) => a[1].localeCompare(b[1]));
}

function SourceManager({ sources, selectedSource, onChange }: { sources: OrderSource[]; selectedSource: string; onChange: (sources: OrderSource[]) => void }) {
  const [label, setLabel] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState('');

  const addSource = async () => {
    if (!label.trim()) return;
    setSaving(true);
    setError('');
    try {
      const response = await fetch('/api/sources', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ label })
      });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || 'Could not add source.');
      onChange([...sources, result].sort((a, b) => a.label.localeCompare(b.label)));
      setLabel('');
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : 'Could not add source.');
    } finally {
      setSaving(false);
    }
  };

  const removeSource = async (source: OrderSource) => {
    if (!window.confirm(`Remove "${source.label}" from future order source choices?`)) return;
    setError('');
    const response = await fetch(`/api/sources/${encodeURIComponent(source.key)}`, { method: 'DELETE' });
    const result = await response.json();
    if (!response.ok) return setError(result.error || 'Could not remove source.');
    onChange(sources.filter((item) => item.key !== source.key));
  };

  return <div className="source-manager">
    <div className="source-manager-add">
      <input value={label} onChange={(event) => setLabel(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter') { event.preventDefault(); void addSource(); } }} placeholder="New source name" />
      <button type="button" disabled={saving || !label.trim()} onClick={() => void addSource()}><Plus size={14} /> Add</button>
    </div>
    <div className="source-manager-list">{sources.map((source) => <div key={source.key}><span>{source.label}{source.key === selectedSource && <small>Selected</small>}</span><button type="button" title={`Remove ${source.label}`} onClick={() => void removeSource(source)}><Trash2 size={14} /></button></div>)}</div>
    {error && <p className="form-error">{error}</p>}
  </div>;
}

function getPaymentOptions(orders: Order[]): [string, string][] {
  const options = new Map<string, string>([['cod', 'Cash on delivery'], ['bacs', 'Direct bank transfer']]);
  orders.forEach((order) => order.paymentMethod && options.set(order.paymentMethod, order.payment));
  return Array.from(options.entries());
}

function AuthScreen({ needsSetup, onAuthenticated }: { needsSetup: boolean; onAuthenticated: (user: CrmUser) => void }) {
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState('');

  const submit = async (event: React.FormEvent) => {
    event.preventDefault();
    setSubmitting(true);
    setError('');
    try {
      const response = await fetch(needsSetup ? '/api/auth/setup' : '/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, email, password })
      });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || 'Could not sign in.');
      onAuthenticated(result.user);
    } catch (submitError) {
      setError(submitError instanceof Error ? submitError.message : 'Could not sign in.');
    } finally {
      setSubmitting(false);
    }
  };

  return <main className="auth-screen"><section className="auth-card">
    <img src="http://localhost/gravy/wp-content/uploads/2026/01/logo1.svg" alt="Gravy" />
    <div><p className="eyebrow">Gravy Chawal CRM</p><h1>{needsSetup ? 'Create owner account' : 'Welcome back'}</h1><p>{needsSetup ? 'Set up the first CRM administrator.' : 'Sign in to manage orders and operations.'}</p></div>
    <form onSubmit={submit}>
      {needsSetup && <label><span>Full name</span><input required value={name} onChange={(event) => setName(event.target.value)} autoComplete="name" /></label>}
      <label><span>Email</span><input required type="email" value={email} onChange={(event) => setEmail(event.target.value)} autoComplete="email" /></label>
      <label><span>Password</span><input required minLength={8} type="password" value={password} onChange={(event) => setPassword(event.target.value)} autoComplete={needsSetup ? 'new-password' : 'current-password'} /></label>
      {error && <p className="form-error">{error}</p>}
      <button type="submit" disabled={submitting}>{submitting ? 'Please wait...' : needsSetup ? 'Create administrator' : 'Sign in'}</button>
    </form>
  </section></main>;
}

function UsersPage({ currentUser }: { currentUser: CrmUser }) {
  const [users, setUsers] = React.useState<CrmUser[]>([]);
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [role, setRole] = React.useState<CrmRole>('viewer');
  const [error, setError] = React.useState('');
  const [saving, setSaving] = React.useState(false);

  const loadUsers = React.useCallback(async () => {
    const response = await fetch('/api/users');
    const result = await response.json();
    if (!response.ok) throw new Error(result.error || 'Could not load users.');
    setUsers(result);
  }, []);

  React.useEffect(() => { void loadUsers().catch((loadError) => setError(loadError.message)); }, [loadUsers]);

  const addUser = async (event: React.FormEvent) => {
    event.preventDefault();
    setSaving(true);
    setError('');
    try {
      const response = await fetch('/api/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, email, password, role })
      });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || 'Could not add user.');
      setUsers((current) => [...current, result]);
      setName('');
      setEmail('');
      setPassword('');
      setRole('viewer');
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : 'Could not add user.');
    } finally {
      setSaving(false);
    }
  };

  const updateRole = async (user: CrmUser, nextRole: CrmRole) => {
    setError('');
    const response = await fetch(`/api/users/${user.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ role: nextRole })
    });
    const result = await response.json();
    if (!response.ok) return setError(result.error || 'Could not update role.');
    setUsers((current) => current.map((item) => item.id === result.id ? result : item));
  };

  const deleteUser = async (user: CrmUser) => {
    if (!window.confirm(`Delete CRM user ${user.name}?`)) return;
    const response = await fetch(`/api/users/${user.id}`, { method: 'DELETE' });
    const result = await response.json();
    if (!response.ok) return setError(result.error || 'Could not delete user.');
    setUsers((current) => current.filter((item) => item.id !== user.id));
  };

  return <section className="users-layout">
    <DataSection title={`${users.length} CRM users`} subtitle="Administrators manage users; managers operate orders; viewers have read-only access.">
      {error && <div className="alert">{error}</div>}
      <div className="users-table"><div className="users-table-head"><span>User</span><span>Role</span><span>Added</span><span>Action</span></div>{users.map((user) => <article key={user.id}>
        <div className="user-identity"><div className="avatar">{initials(user.name)}</div><div><strong>{user.name}</strong><span>{user.email}</span></div></div>
        <select value={user.role} disabled={user.id === currentUser.id} onChange={(event) => void updateRole(user, event.target.value as CrmRole)}>{roleOptions.map(([value, label]) => <option value={value} key={value}>{label}</option>)}</select>
        <span>{formatUserDate(user.createdAt)}</span>
        <button className="delete-user-button" type="button" disabled={user.id === currentUser.id} onClick={() => void deleteUser(user)}><Trash2 size={15} /> Delete</button>
      </article>)}</div>
    </DataSection>
    <section className="panel add-user-panel"><div className="panel-head"><h2>Add CRM user</h2><UserPlus size={18} /></div><form onSubmit={addUser}>
      <label><span>Full name</span><input required value={name} onChange={(event) => setName(event.target.value)} /></label>
      <label><span>Email</span><input required type="email" value={email} onChange={(event) => setEmail(event.target.value)} /></label>
      <label><span>Temporary password</span><input required minLength={8} type="password" value={password} onChange={(event) => setPassword(event.target.value)} /></label>
      <label><span>User role</span><select value={role} onChange={(event) => setRole(event.target.value as CrmRole)}>{roleOptions.map(([value, label]) => <option value={value} key={value}>{label}</option>)}</select></label>
      <button type="submit" disabled={saving}><UserPlus size={16} /> {saving ? 'Adding...' : 'Add user'}</button>
    </form></section>
  </section>;
}

const roleOptions: [CrmRole, string][] = [['admin', 'Administrator'], ['manager', 'Manager'], ['viewer', 'Viewer']];
function roleLabel(role: CrmRole) { return roleOptions.find(([value]) => value === role)?.[1] || role; }
function formatUserDate(value: string) { return new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium' }).format(new Date(value)); }

async function downloadDocument(document: { kind: 'quotation' | 'invoice'; customer: string; documentNumber: string; documentDate: string; expiryDate: string; deliveryCharge: number; items: QuotationItem[]; notes: string; terms: string }) {
  const { jsPDF } = await import('jspdf');
  const isInvoice = document.kind === 'invoice';
  const documentLabel = isInvoice ? 'INVOICE' : 'QUOTATION';
  const pdf = new jsPDF({ unit: 'mm', format: 'a4' });
  const pageWidth = pdf.internal.pageSize.getWidth();
  const margin = 18;
  const right = pageWidth - margin;
  const currency = (value: number) => `PKR ${new Intl.NumberFormat('en-PK', { maximumFractionDigits: 0 }).format(value || 0)}`;
  const dateLabel = (value: string) => value ? new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium' }).format(new Date(`${value}T00:00:00`)) : 'Not specified';

  pdf.setFillColor(195, 32, 38);
  pdf.rect(0, 0, pageWidth, 34, 'F');
  try {
    pdf.addImage(await loadInvoiceLogo(), 'PNG', margin, 6, 38.7, 25);
  } catch {
    pdf.setTextColor(255, 255, 255);
    pdf.setFont('helvetica', 'bold');
    pdf.setFontSize(16);
    pdf.text('GRAVY', margin, 19);
  }
  pdf.setTextColor(255, 255, 255);
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(15);
  pdf.text(`${documentLabel} #${document.documentNumber}`, right, 17, { align: 'right' });
  pdf.setFont('helvetica', 'normal');
  pdf.setFontSize(8);
  pdf.text(`${isInvoice ? 'Invoice' : 'Quote'} date: ${dateLabel(document.documentDate)}`, right, 24, { align: 'right' });

  pdf.setTextColor(23, 32, 51);
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(10);
  pdf.text(isInvoice ? 'INVOICE FOR' : 'QUOTATION FOR', margin, 48);
  if (!isInvoice) pdf.text('VALID UNTIL', 132, 48);
  pdf.setDrawColor(226, 232, 240);
  pdf.line(margin, 51, right, 51);
  pdf.setFontSize(11);
  pdf.text(document.customer, margin, 59);
  pdf.setFont('helvetica', 'normal');
  pdf.setFontSize(9);
  if (!isInvoice) pdf.text(dateLabel(document.expiryDate), 132, 59);

  let y = 70;
  pdf.setFillColor(248, 250, 252);
  pdf.rect(margin, y, pageWidth - margin * 2, 10, 'F');
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(8);
  pdf.text('ITEM', margin + 3, y + 6.5);
  pdf.text('QTY', 135, y + 6.5, { align: 'right' });
  pdf.text('RATE', 164, y + 6.5, { align: 'right' });
  pdf.text('AMOUNT', right - 2, y + 6.5, { align: 'right' });
  y += 10;
  document.items.forEach((item) => {
    const amount = item.quantity * item.rate;
    const nameLines = pdf.splitTextToSize(item.name || 'Item', 86);
    const rowHeight = Math.max(11, nameLines.length * 5 + 5);
    pdf.setFont('helvetica', 'normal');
    pdf.setFontSize(9);
    pdf.text(nameLines, margin + 3, y + 6);
    pdf.text(String(item.quantity), 135, y + 6, { align: 'right' });
    pdf.text(currency(item.rate), 164, y + 6, { align: 'right' });
    pdf.setFont('helvetica', 'bold');
    pdf.text(currency(amount), right - 2, y + 6, { align: 'right' });
    pdf.setDrawColor(238, 242, 247);
    pdf.line(margin, y + rowHeight, right, y + rowHeight);
    y += rowHeight;
  });

  const subtotal = sum(document.items.map((item) => item.quantity * item.rate));
  y += 8;
  pdf.setFont('helvetica', 'normal');
  pdf.setFontSize(9);
  pdf.setTextColor(71, 85, 105);
  pdf.text('Subtotal', 132, y);
  pdf.text(currency(subtotal), right, y, { align: 'right' });
  y += 7;
  pdf.text('Delivery charges', 132, y);
  pdf.text(currency(document.deliveryCharge), right, y, { align: 'right' });
  y += 5;
  pdf.setDrawColor(226, 232, 240);
  pdf.line(132, y, right, y);
  pdf.setFont('helvetica', 'bold');
  pdf.setTextColor(23, 32, 51);
  pdf.text('TOTAL', 132, y + 8);
  pdf.setTextColor(195, 32, 38);
  pdf.setFontSize(14);
  pdf.text(currency(subtotal + document.deliveryCharge), right, y + 8, { align: 'right' });

  y += 18;
  pdf.setTextColor(71, 85, 105);
  pdf.setFontSize(8);
  pdf.setFont('helvetica', 'bold');
  if (document.notes) {
    pdf.text('CUSTOMER NOTES', margin, y);
    pdf.setFont('helvetica', 'normal');
    pdf.text(pdf.splitTextToSize(document.notes, 170), margin, y + 5);
    y += 16;
  }
  if (document.terms) {
    pdf.setFont('helvetica', 'bold');
    pdf.text('TERMS AND CONDITIONS', margin, y);
    pdf.setFont('helvetica', 'normal');
    pdf.text(pdf.splitTextToSize(document.terms, 170), margin, y + 5);
  }
  pdf.save(`gravy-${document.kind}-${document.documentNumber}.pdf`);
}

async function downloadInvoice(order: Order) {
  const { jsPDF } = await import('jspdf');
  const pdf = new jsPDF({ unit: 'mm', format: 'a4' });
  const pageWidth = pdf.internal.pageSize.getWidth();
  const margin = 18;
  const right = pageWidth - margin;
  const currency = (value: number) => `PKR ${new Intl.NumberFormat('en-PK', { maximumFractionDigits: 0 }).format(value || 0)}`;

  pdf.setFillColor(195, 32, 38);
  pdf.rect(0, 0, pageWidth, 34, 'F');
  try {
    const logo = await loadInvoiceLogo();
    pdf.addImage(logo, 'PNG', margin, 6, 38.7, 25);
  } catch {
    pdf.setTextColor(255, 255, 255);
    pdf.setFont('helvetica', 'bold');
    pdf.setFontSize(16);
    pdf.text('GRAVY', margin, 19);
  }
  pdf.setTextColor(255, 255, 255);
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(15);
  pdf.text(`INVOICE #${order.number}`, right, 17, { align: 'right' });
  pdf.setFontSize(8);
  pdf.setFont('helvetica', 'normal');
  pdf.text(new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium' }).format(new Date(order.date)), right, 24, { align: 'right' });

  let y = 46;
  pdf.setTextColor(23, 32, 51);
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(10);
  pdf.text('BILL TO', margin, y);
  pdf.text('ORDER DETAILS', 116, y);
  pdf.setDrawColor(226, 232, 240);
  pdf.line(margin, y + 3, right, y + 3);
  y += 10;

  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(11);
  pdf.text(order.customer || 'Guest customer', margin, y);
  pdf.setFont('helvetica', 'normal');
  pdf.setFontSize(9);
  if (order.phone) pdf.text(order.phone, margin, y + 6);
  if (order.email) pdf.text(order.email, margin, y + (order.phone ? 12 : 6));

  const details = [
    ['Status', labelStatus(order.status)],
    ['Source', order.source],
    ['Delivery zone', order.zone],
    ['Delivery charges', currency(order.deliveryCharge)],
    ['Payment', order.payment]
  ];
  details.forEach(([label, value], index) => {
    const lineY = y + index * 6;
    pdf.setFont('helvetica', 'bold');
    pdf.text(`${label}:`, 116, lineY);
    pdf.setFont('helvetica', 'normal');
    pdf.text(String(value), right, lineY, { align: 'right', maxWidth: 56 });
  });

  y = 88;
  pdf.setFillColor(248, 250, 252);
  pdf.rect(margin, y, pageWidth - margin * 2, 10, 'F');
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(8);
  pdf.text('PRODUCT', margin + 3, y + 6.5);
  pdf.text('QTY', 137, y + 6.5, { align: 'right' });
  pdf.text('UNIT PRICE', 165, y + 6.5, { align: 'right' });
  pdf.text('TOTAL', right - 2, y + 6.5, { align: 'right' });
  y += 10;

  order.products.forEach((product) => {
    const nameLines = pdf.splitTextToSize(product.name, 91);
    const rowHeight = Math.max(11, nameLines.length * 5 + 5);
    if (y + rowHeight > 265) {
      pdf.addPage();
      y = 20;
    }
    pdf.setFont('helvetica', 'normal');
    pdf.setFontSize(9);
    pdf.text(nameLines, margin + 3, y + 6);
    pdf.text(String(product.quantity), 137, y + 6, { align: 'right' });
    pdf.text(currency(product.quantity ? product.total / product.quantity : product.total), 165, y + 6, { align: 'right' });
    pdf.setFont('helvetica', 'bold');
    pdf.text(currency(product.total), right - 2, y + 6, { align: 'right' });
    pdf.setDrawColor(238, 242, 247);
    pdf.line(margin, y + rowHeight, right, y + rowHeight);
    y += rowHeight;
  });

  y += 8;
  const productSubtotal = sum(order.products.map((product) => product.total));
  const totalLabelX = 132;
  pdf.setFontSize(9);
  pdf.setTextColor(71, 85, 105);
  pdf.setFont('helvetica', 'normal');
  pdf.text('Product subtotal', totalLabelX, y);
  pdf.text(currency(productSubtotal), right, y, { align: 'right' });
  y += 7;
  pdf.text('Delivery charges', totalLabelX, y);
  pdf.text(currency(order.deliveryCharge), right, y, { align: 'right' });
  y += 3;
  pdf.setDrawColor(226, 232, 240);
  pdf.line(totalLabelX, y, right, y);
  y += 8;
  pdf.setFont('helvetica', 'bold');
  pdf.setFontSize(10);
  pdf.setTextColor(23, 32, 51);
  pdf.text('ORDER TOTAL', totalLabelX, y);
  pdf.setTextColor(195, 32, 38);
  pdf.setFontSize(14);
  pdf.text(currency(order.total), right, y, { align: 'right' });
  pdf.setTextColor(100, 116, 139);
  pdf.setFont('helvetica', 'normal');
  pdf.setFontSize(8);
  pdf.text('Thank you for ordering from Gravy Chawal.', margin, 282);
  pdf.text(`Generated ${new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium', timeStyle: 'short' }).format(new Date())}`, right, 282, { align: 'right' });
  pdf.save(`gravy-invoice-${order.number}.pdf`);
}

async function loadInvoiceLogo() {
  const response = await fetch('/api/brand-logo');
  if (!response.ok) throw new Error('Could not load invoice logo.');
  const svg = await response.text();
  const blobUrl = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
  try {
    const image = await new Promise<HTMLImageElement>((resolveImage, rejectImage) => {
      const element = new Image();
      element.onload = () => resolveImage(element);
      element.onerror = () => rejectImage(new Error('Could not render invoice logo.'));
      element.src = blobUrl;
    });
    const canvas = document.createElement('canvas');
    canvas.width = 440;
    canvas.height = 284;
    const context = canvas.getContext('2d');
    if (!context) throw new Error('Canvas is unavailable.');
    context.drawImage(image, 0, 0, canvas.width, canvas.height);
    return canvas.toDataURL('image/png');
  } finally {
    URL.revokeObjectURL(blobUrl);
  }
}

function LoadingScreen() { return <div className="loading-screen"><RefreshCw size={24} /><strong>Loading CRM dashboard</strong></div>; }
function readPage(): Page {
  const page = window.location.hash.replace('#', '') as Page;
  return pageTitles[page] ? page : 'dashboard';
}
function labelStatus(status: string) { return statusLabels[status] || status.replace(/-/g, ' '); }
function stockLabel(stock: string) { return ({ instock: 'In stock', outofstock: 'Out of stock', onbackorder: 'Backorder' } as Record<string, string>)[stock] || stock; }
function isPaidOrder(order: Order) { return !['cancelled', 'failed', 'refunded'].includes(order.status); }
function money(value: number) { return new Intl.NumberFormat('en-PK', { style: 'currency', currency: 'PKR', maximumFractionDigits: 0 }).format(value || 0); }
function formatDate(value: string) { return new Intl.DateTimeFormat('en-PK', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }).format(new Date(value)); }
function formatTime(value: string) { return new Intl.DateTimeFormat('en-PK', { hour: 'numeric', minute: '2-digit' }).format(new Date(value)); }
function formatDeliveryTime(value: string) {
  if (!value) return 'Not provided';
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? value : new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium', timeStyle: 'short' }).format(date);
}
function formatEventDate(value: string) {
  if (!value) return 'Not provided';
  const date = new Date(`${value}T00:00:00`);
  return Number.isNaN(date.getTime()) ? value : new Intl.DateTimeFormat('en-PK', { dateStyle: 'medium' }).format(date);
}
function toDateTimeLocal(value: string) {
  if (!value) return '';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value.slice(0, 16);
  const local = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
  return local.toISOString().slice(0, 16);
}
function orderSubtotal(order: Order) { return Math.max(0, order.total - order.deliveryCharge); }
function initials(name: string) { return name.split(' ').map((part) => part[0]).join('').slice(0, 2).toUpperCase(); }
function unique(values: string[]) { return Array.from(new Set(values.filter(Boolean))).sort(); }
function sum(values: number[]) { return values.reduce((total, value) => total + value, 0); }

createRoot(document.getElementById('root')!).render(<React.StrictMode><App /></React.StrictMode>);
