/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * Deliveries page — replicated from the operations console (nearle_console/
 * deliveries), rebuilt against the shared console UI kit (`./consoleUi`) so it
 * matches the source design (gradient header, KPI cards, batch + status pill
 * tabs, STATUS_META colours, metric-pill table). The board loads the day's
 * deliveries once and filters client-side by delivery wave, lifecycle status, and
 * keyword. Rider write-actions (reassign/cancel/notify) need the dispatch + FCM
 * backends this tenant doesn't expose, so they surface an "awaiting backend" note.
 */

import React, { useMemo, useState } from 'react';
import { createPortal } from 'react-dom';
import {
  Truck, Clock, CheckCircle2, XCircle, Calendar, Sun, Sunset, Moon, Layers, UserCheck, MapPin, Phone, Package, Loader2, X, Bike,
} from 'lucide-react';
import { useFiestaDeliverySummary, useFiestaDeliveries, useFiestaRiders, useFiestaOrderDetails, useFiestaChangeRider, useFiestaNotifyRider } from '../services/fiestaQueries';
import { FIESTA_TENANT_ID, FIESTA_APPLOCATION_ID, RIDER_MESSAGES, RiderNotReachableError, num as fnum, str as fstr, ymd, type Row } from '../services/fiestaApi';
import { shortTime } from '../services/fiestaMappers';
import AwaitingApi from './AwaitingApi';
import {
  GradientHeader, LiveStatus, KpiStrip, Pill, StatusChip, MetricPill, SearchPill, FilterBar, TH_STYLE,
  DELIVERY_STATUS, statusColor, BRAND, BRAND_LIGHT, TEXT, TEXT_2, TEXT_3, BORDER, DIVIDER, SURFACE_ALT, tint, soft, edge,
} from './consoleUi';

interface DeliveriesViewProps { searchQuery?: string; locationid?: number; tenantId?: number; applocationid?: number; date?: string; }

type DeliveryStatus = 'pending' | 'accepted' | 'arrived' | 'picked' | 'active' | 'skipped' | 'delivered' | 'cancelled';
const STATUS_TABS: Array<{ key: DeliveryStatus; label: string }> = [
  { key: 'pending', label: 'Pending' }, { key: 'accepted', label: 'Accepted' }, { key: 'arrived', label: 'Arrived' },
  { key: 'picked', label: 'Picked' }, { key: 'active', label: 'Active' }, { key: 'skipped', label: 'Skipped' },
  { key: 'delivered', label: 'Delivered' }, { key: 'cancelled', label: 'Cancelled' },
];

// Batch waves — canonical half-open hour ranges (match Dispatch).
type BatchId = 'all' | 'morning' | 'afternoon' | 'evening';
const BATCHES: Array<{ id: BatchId; label: string; range: string; color: string; icon: typeof Sun }> = [
  { id: 'all', label: 'All', range: 'Full day', color: '#7c3aed', icon: Layers },
  { id: 'morning', label: 'Morning', range: '12 AM – 8 AM', color: '#0ea5e9', icon: Sun },
  { id: 'afternoon', label: 'Afternoon', range: '9 AM – 12:30 PM', color: '#f59e0b', icon: Sunset },
  { id: 'evening', label: 'Evening', range: '4 PM – 7 PM', color: '#6366f1', icon: Moon },
];
function rowHourFrac(r: Row): number | null {
  const m = (fstr(r.assigntime) || fstr(r.deliverytime) || fstr(r.deliverydate)).match(/[ T](\d{1,2}):(\d{2})/);
  return m ? Number(m[1]) + Number(m[2]) / 60 : null;
}
function inBatch(r: Row, b: BatchId): boolean {
  if (b === 'all') return true;
  const h = rowHourFrac(r);
  if (h == null) return false;
  if (b === 'morning') return h >= 0 && h < 8;
  if (b === 'afternoon') return h >= 9 && h < 12.5;
  return h >= 16 && h < 19;
}

export default function DeliveriesView({ searchQuery = '', locationid, tenantId = FIESTA_TENANT_ID, applocationid = FIESTA_APPLOCATION_ID, date }: DeliveriesViewProps) {
  const today = new Date();
  const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
  const dayOffset = (n: number) => { const d = new Date(); d.setDate(d.getDate() - n); return ymd(d); };
  const dayAhead = (n: number) => { const d = new Date(); d.setDate(d.getDate() + n); return ymd(d); };
  const [fromdate, setFromdate] = React.useState<string>(date || dayOffset(6));
  const [todate, setTodate] = React.useState<string>(date || ymd(today));
  
  React.useEffect(() => {
    if (date) {
      setFromdate(date);
      setTodate(date);
    }
  }, [date]);
  const presets = [
    { key: 'today', label: 'Today',       from: ymd(today),      to: ymd(today)  },
    { key: 'yesterday', label: 'Yesterday', from: dayOffset(1),  to: dayOffset(1) },
    { key: '7d',    label: 'Last 7 Days', from: dayOffset(6),    to: ymd(today)  },
    { key: 'month', label: 'This Month',  from: ymd(monthStart), to: dayAhead(7) },
  ];
  const activePreset = presets.find((p) => p.from === fromdate && p.to === todate)?.key ?? 'custom';

  const batch: BatchId = 'all';
  const [status, setStatus] = useState<DeliveryStatus>('pending');
  const [localSearch, setLocalSearch] = useState('');
  const [detailRow, setDetailRow] = useState<Row | null>(null);

  // Scope to the user's store when a locationid is supplied (server-side per the
  // backend's deliverysummary/getdeliveries locationid param). getDeliveries loads
  // the whole day (status='all', large pagesize); status/search filter client-side.
  const summaryQ = useFiestaDeliverySummary({ tenantid: tenantId, fromdate, todate, locationid });
  const deliveriesQ = useFiestaDeliveries({ tenantid: tenantId, fromdate, todate, locationid, status: 'all', pagesize: 200 });
  // Scoped by app-location, not tenant: rider records leave app_users.tenantid
  // unset, so a tenant-scoped call returns an empty list and the change-rider
  // dropdown would have nothing in it. Prefer the app-location the visible
  // deliveries name, falling back to the caller's.
  const rowApplocationId = useMemo(
    () => fnum((deliveriesQ.data ?? []).find((r) => fnum(r.applocationid))?.applocationid),
    [deliveriesQ.data],
  );
  const ridersQ = useFiestaRiders({ applocationid: rowApplocationId || applocationid || undefined });

  const allRows = deliveriesQ.data ?? [];
  const summary = summaryQ.data;

  const batchRows = useMemo(() => allRows.filter((r) => (!locationid || fnum(r.locationid) === locationid) && inBatch(r, batch)), [allRows, batch, locationid]);
  const statusCounts = useMemo(() => {
    const acc: Record<string, number> = {};
    for (const r of batchRows) { const s = fstr(r.orderstatus).toLowerCase(); acc[s] = (acc[s] ?? 0) + 1; }
    return acc;
  }, [batchRows]);
  const rows = useMemo(() => {
    const term = (localSearch || searchQuery).toLowerCase();
    return batchRows.filter((r) => {
      if (fstr(r.orderstatus).toLowerCase() !== status) return false;
      if (!term) return true;
      return [r.orderid, r.deliverycustomer, r.deliveryaddress, r.deliverysuburb, r.pickupcustomer, r.ridername, r.username].some((f) => fstr(f).toLowerCase().includes(term));
    });
  }, [batchRows, status, localSearch, searchQuery]);

  const activeFleet = (ridersQ.data ?? []).filter((r) => fstr(r.starttime)).length;
  const total = summary?.total ?? 0;
  const pct = (n: number) => (total > 0 ? `${Math.round((n / total) * 100)}% of total` : 'In range');
  const kpis = [
    { label: 'Total Deliveries', value: total.toLocaleString('en-IN'), color: '#6366f1', icon: <Truck size={20} />, badge: undefined },
    { label: 'Pending', value: (summary?.pending ?? 0).toLocaleString('en-IN'), color: '#f59e0b', icon: <Clock size={20} />, badge: pct(summary?.pending ?? 0) },
    { label: 'Delivered', value: (summary?.delivered ?? 0).toLocaleString('en-IN'), color: '#10b981', icon: <CheckCircle2 size={20} />, badge: pct(summary?.delivered ?? 0) },
    { label: 'Cancelled', value: (summary?.cancelled ?? 0).toLocaleString('en-IN'), color: '#f43f5e', icon: <XCircle size={20} />, badge: pct(summary?.cancelled ?? 0) },
  ];

  return (
    <div className="animate-in fade-in duration-300">
      <div className="mb-4">

        <KpiStrip items={kpis} loading={summaryQ.isLoading} />
      </div>

      {/* Date + waves */}
      <FilterBar className="mb-4">
        <div className="flex flex-col lg:flex-row lg:items-center justify-between gap-3">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="inline-flex items-center gap-1.5 text-[10px] font-extrabold uppercase tracking-widest pr-1" style={{ color: TEXT_2 }}><Calendar size={13} style={{ color: BRAND }} /> View</span>
            {presets.map((p) => (
              <React.Fragment key={p.key}><Pill active={activePreset === p.key} color={BRAND} onClick={() => { setFromdate(p.from); setTodate(p.to); }}>{p.label}</Pill></React.Fragment>
            ))}
          </div>
          <div className="flex items-center gap-2 text-xs">
            <input type="date" value={fromdate} max={todate} onChange={(e) => setFromdate(e.target.value)} className="rounded-full outline-none font-semibold" style={{ padding: '6px 12px', border: `1.5px solid ${edge('#f59e0b')}`, background: tint('#f59e0b'), color: '#b45309' }} />
            <span style={{ color: TEXT_3 }}>→</span>
            <input type="date" value={todate} min={fromdate} onChange={(e) => setTodate(e.target.value)} className="rounded-full outline-none font-semibold" style={{ padding: '6px 12px', border: `1.5px solid ${edge('#f59e0b')}`, background: tint('#f59e0b'), color: '#b45309' }} />
          </div>
        </div>
      </FilterBar>

      {/* Status tabs + search */}
      <FilterBar className="mb-4">
        <div className="flex flex-col lg:flex-row lg:items-center gap-3">
          <div className="flex items-center gap-2 overflow-x-auto custom-scrollbar no-scrollbar py-0.5 flex-1 min-w-0 touch-scrolling">
            {STATUS_TABS.map((t) => (
              <React.Fragment key={t.key}>
                <Pill active={status === t.key} color={BRAND} onClick={() => setStatus(t.key)} count={statusCounts[t.key] ?? 0}>{t.label}</Pill>
              </React.Fragment>
            ))}
          </div>
          <div className="w-full lg:w-72 lg:shrink-0"><SearchPill value={localSearch} onChange={setLocalSearch} placeholder="Search by order, rider…" /></div>
        </div>
      </FilterBar>

      {/* Table */}
      <div className="bg-white border overflow-hidden" style={{ borderColor: BORDER }}>
        <div className="overflow-x-auto">
          <table className="w-full" style={{ minWidth: 1240 }}>
            <thead>
              <tr>{['S.No', 'Tenant', 'Order ID', 'Pickup', 'Delivery', 'Rider', 'KMS', 'Amount', 'Status', 'Notes', 'Action'].map((h, i) => (<th key={i} className="px-3 py-2.5 text-left" style={TH_STYLE}>{h}</th>))}</tr>
            </thead>
            <tbody>
              {deliveriesQ.isLoading ? (
                <tr><td colSpan={11} className="px-3 py-12 text-center" style={{ color: TEXT_3 }}><span className="inline-flex items-center gap-2 text-xs font-semibold"><Loader2 size={15} className="animate-spin" style={{ color: BRAND }} /> Loading deliveries…</span></td></tr>
              ) : rows.length === 0 ? (
                <tr><td colSpan={11} className="px-3 py-12 text-center text-xs" style={{ color: TEXT_3 }}>No {status} deliveries in this wave. Try another status, wave, or date.</td></tr>
              ) : (
                rows.map((r, i) => {
                  const st = fstr(r.orderstatus).toLowerCase();
                  const rider = fstr(r.ridername) || fstr(r.username);
                  const kms = fnum(r.kms); const actualKms = fnum(r.actualkms) || fnum(r.riderkms);
                  const charge = fnum(r.deliverycharges); const amt = fnum(r.deliveryamt);
                  const tenant = fstr(r.tenantname) || fstr(r.pickupcustomer);
                  // Pickup/Delivery: the backend often leaves customer/contact blank for
                  // app-created jobs but populates the address — fall back so cells aren't bare.
                  const pickupName = fstr(r.pickupcustomer) || fstr(r.pickupcontactno);
                  const pickupAddr = fstr(r.pickupsuburb) || fstr(r.pickuplocation) || fstr(r.Pickupaddress) || fstr(r.pickupaddress);
                  const dropName = fstr(r.deliverycustomer) || fstr(r.deliverycontactno);
                  const dropAddr = fstr(r.deliveryaddress) || fstr(r.deliverylocation) || fstr(r.deliverysuburb);
                  const notes = fstr(r.ordernotes) || fstr(r.notes);
                  return (
                    <tr key={fstr(r.deliveryid) || fstr(r.orderid) || i} className="transition-colors align-top" style={{ borderBottom: `1px solid ${DIVIDER}` }}
                      onMouseEnter={(e) => (e.currentTarget.style.background = SURFACE_ALT)} onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}>
                      <td className="px-3 py-2.5 font-mono" style={{ color: TEXT_3 }}>{i + 1}</td>
                      <td className="px-3 py-2.5">
                        <p className="font-bold text-[12px] truncate max-w-[150px]" style={{ color: TEXT }}>{tenant || '—'}</p>
                        {fstr(r.tenantcity) && <p className="text-[10px] truncate max-w-[150px]" style={{ color: TEXT_2 }}>{fstr(r.tenantcity)}</p>}
                      </td>
                      <td className="px-3 py-2.5">
                        <p className="font-extrabold font-mono text-[13px]" style={{ color: TEXT }}>{fstr(r.orderid) || `DLV-${fstr(r.deliveryid)}`}</p>
                        <p className="text-[10px]" style={{ color: TEXT_2 }}>{shortTime(r.assigntime || r.deliverydate)}</p>
                      </td>
                      <td className="px-3 py-2.5">
                        <p className="font-bold text-[12px] truncate max-w-[160px]" style={{ color: TEXT }}>{pickupName || pickupAddr || '—'}</p>
                        <p className="text-[10px] truncate max-w-[160px]" style={{ color: TEXT_2 }}>{pickupName ? pickupAddr : ''}</p>
                      </td>
                      <td className="px-3 py-2.5">
                        <p className="font-bold text-[12px] truncate max-w-[160px]" style={{ color: TEXT }}>{dropName || dropAddr || '—'}</p>
                        <p className="text-[10px] truncate max-w-[160px]" style={{ color: TEXT_2 }}>{dropName ? dropAddr : ''}</p>
                      </td>
                      <td className="px-3 py-2.5">
                        {rider ? (
                          <span className="inline-flex items-center gap-2">
                            <span className="rounded-full flex items-center justify-center shrink-0" style={{ width: 26, height: 26, background: soft('#8b5cf6'), color: '#8b5cf6' }}><Bike size={13} /></span>
                            <span className="font-bold text-[12px] truncate max-w-[100px]" style={{ color: TEXT }}>{rider}</span>
                          </span>
                        ) : <span className="text-[11px] italic" style={{ color: TEXT_3 }}>Unassigned</span>}
                      </td>
                      <td className="px-3 py-2.5">
                        <div className="flex flex-col items-start gap-1">
                          <MetricPill color="#ef4444" minWidth={64}>{kms ? kms.toFixed(1) : '—'}</MetricPill>
                          {actualKms > 0 && <MetricPill color="#10b981" minWidth={64}>{actualKms.toFixed(1)}</MetricPill>}
                        </div>
                      </td>
                      <td className="px-3 py-2.5">
                        <div className="flex flex-col items-start gap-1">
                          {charge > 0 && <MetricPill color="#ef4444" minWidth={72}>₹{charge.toLocaleString('en-IN')}</MetricPill>}
                          {amt > 0 && <MetricPill color="#10b981" minWidth={72}>₹{amt.toLocaleString('en-IN')}</MetricPill>}
                          {charge === 0 && amt === 0 && <span style={{ color: TEXT_3 }}>—</span>}
                        </div>
                      </td>
                      <td className="px-3 py-2.5"><StatusChip label={st || '—'} color={statusColor(DELIVERY_STATUS, st)} /></td>
                      <td className="px-3 py-2.5">
                        <p className="text-[11px] truncate max-w-[160px]" style={{ color: notes ? TEXT_2 : TEXT_3 }} title={notes}>{notes || '—'}</p>
                      </td>
                      <td className="px-3 py-2.5 text-right">
                        <button onClick={() => setDetailRow(r)} className="rounded-full font-extrabold cursor-pointer" style={{ padding: '4px 12px', fontSize: 11, color: BRAND, background: tint(BRAND), border: `1px solid ${edge(BRAND)}` }}>View</button>
                      </td>
                    </tr>
                  );
                })
              )}
            </tbody>
          </table>
        </div>
        <div className="px-4 py-2.5 border-t text-[10px] font-bold uppercase tracking-wider" style={{ borderColor: BORDER, background: SURFACE_ALT, color: TEXT_2 }}>
          {rows.length} {status} · {BATCHES.find((b) => b.id === batch)?.label} wave
        </div>
      </div>

      {detailRow && <DeliveryDetailModal row={detailRow} riders={ridersQ.data ?? []} onClose={() => setDetailRow(null)} />}
    </div>
  );
}

/**
 * Change-rider / notify controls for one delivery.
 *
 * Change-rider is offered only while the delivery is still pending, accepted or
 * arrived — reassigning resets orderstatus to 'pending', so allowing it once the
 * parcel is picked up or delivered would rewind a completed journey.
 *
 * Notify and reassign are reported separately on purpose. The reassign is
 * committed the moment it returns; a push that then fails leaves a rider
 * holding work nobody told them about, which is worth saying out loud rather
 * than folding into a single "done".
 */
function RiderActions({ row, riders }: { row: Row; riders: Row[] }) {
  const st = fstr(row.orderstatus).toLowerCase();
  const deliveryid = fnum(row.deliveryid);
  const orderheaderid = fnum(row.orderheaderid);
  const canChange = ['pending', 'accepted', 'arrived'].includes(st) && deliveryid > 0;
  const canNotify = st !== 'delivered' && st !== 'cancelled';

  const [picked, setPicked] = useState(0);
  const [msg, setMsg] = useState('');
  const changeMut = useFiestaChangeRider();
  const notifyMut = useFiestaNotifyRider();

  const options = useMemo(
    () =>
      riders
        .map((r) => ({
          id: fnum(r.userid),
          label: (fstr(r.fullname) || `${fstr(r.firstname)} ${fstr(r.lastname)}`).trim(),
          token: fstr(r.userfcmtoken),
        }))
        .filter((o) => o.id > 0 && o.label),
    [riders],
  );

  // The rider currently on the delivery. Deliveries carry the token on the row
  // itself, so notifying does not depend on them still being in the on-duty list.
  const currentToken = fstr(row.userfcmtoken);

  const push = async (token: string, body: string, data?: Record<string, string>, okLabel = 'Rider notified') => {
    try {
      await notifyMut.mutateAsync({ token, body, data });
      setMsg(okLabel);
    } catch (err) {
      setMsg(
        err instanceof RiderNotReachableError
          ? 'Not sent — this rider has no device registered'
          : 'Not sent — the push failed, tell them another way',
      );
    }
  };

  const handleChange = async () => {
    if (!picked) return;
    const option = options.find((o) => o.id === picked);
    try {
      await changeMut.mutateAsync({ deliveryid, orderheaderid, userid: picked });
      setMsg(`Moved to ${option?.label ?? 'rider'} · notifying…`);
      await push(option?.token ?? '', RIDER_MESSAGES.reassigned, undefined, `Moved to ${option?.label ?? 'rider'} · notified`);
    } catch {
      setMsg('Could not change the rider — please retry.');
    }
  };

  const busy = changeMut.isPending || notifyMut.isPending;

  return (
    <div className="rounded-xl p-3" style={{ background: SURFACE_ALT, border: `1px solid ${BORDER}` }}>
      <p className="text-[10px] font-extrabold uppercase tracking-wider mb-2" style={{ color: TEXT_2 }}>Rider actions</p>

      {canChange ? (
        <div className="flex flex-wrap items-center gap-2">
          <select
            value={picked}
            onChange={(e) => setPicked(Number(e.target.value))}
            disabled={busy}
            className="rounded-full font-bold text-[11px] outline-none cursor-pointer disabled:opacity-50"
            style={{ padding: '6px 10px', border: `1px solid ${edge(BRAND)}`, background: '#fff', color: BRAND, maxWidth: 200 }}
          >
            <option value={0}>{options.length ? 'Change rider…' : 'No riders on duty'}</option>
            {options.map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
          </select>
          <button
            onClick={handleChange}
            disabled={!picked || busy}
            className="rounded-full font-extrabold cursor-pointer text-white disabled:opacity-40 disabled:cursor-not-allowed"
            style={{ padding: '6px 14px', fontSize: 11, background: `linear-gradient(135deg, ${BRAND}, ${BRAND_LIGHT})` }}
          >
            {changeMut.isPending ? 'Moving…' : 'Change'}
          </button>
        </div>
      ) : (
        <p className="text-[11px] font-medium" style={{ color: TEXT_3 }}>
          {st === 'delivered' || st === 'cancelled'
            ? `This delivery is ${st} — the rider can no longer be changed.`
            : 'The rider can only be changed while a delivery is pending, accepted or arrived.'}
        </p>
      )}

      {canNotify && (
        <div className="flex flex-wrap items-center gap-2 mt-2 pt-2" style={{ borderTop: `1px solid ${DIVIDER}` }}>
          <button
            onClick={() => push(currentToken, RIDER_MESSAGES.reminder)}
            disabled={busy}
            className="rounded-full font-bold cursor-pointer disabled:opacity-40"
            style={{ padding: '5px 12px', fontSize: 11, color: BRAND, background: tint(BRAND), border: `1px solid ${edge(BRAND)}` }}
          >
            Notify rider
          </button>
          <button
            onClick={() =>
              push(currentToken, RIDER_MESSAGES.cancelled(fstr(row.orderid) || `DLV-${deliveryid}`), { type: 'cancel' }, 'Cancellation sent')
            }
            disabled={busy}
            title="Tells the rider app to drop this delivery"
            className="rounded-full font-bold cursor-pointer disabled:opacity-40"
            style={{ padding: '5px 12px', fontSize: 11, color: '#b91c1c', background: '#fef2f2', border: '1px solid #fecaca' }}
          >
            Send cancellation
          </button>
        </div>
      )}

      {msg && <p className="text-[11px] font-semibold mt-2" style={{ color: TEXT_2 }}>{msg}</p>}
    </div>
  );
}

// ── Delivery details modal ──────────────────────────────────────────────────────
function DeliveryDetailModal({ row, riders, onClose }: { row: Row; riders: Row[]; onClose: () => void }) {
  const orderheaderid = row.orderheaderid ?? row.orderid;
  const detailsQ = useFiestaOrderDetails(orderheaderid as number | string);
  const lines = (detailsQ.data ?? []).map((d) => {
    const quantity = fnum(d.quantity) || fnum(d.qty) || fnum(d.orderqty);
    const price = fnum(d.price) || fnum(d.unitprice) || fnum(d.retailprice);
    return { name: fstr(d.productname) || fstr(d.itemname) || 'Item', quantity, price, lineTotal: fnum(d.amount) || fnum(d.productsumprice) || price * quantity };
  });
  const st = fstr(row.orderstatus).toLowerCase();
  const rider = fstr(row.ridername) || fstr(row.username);
  const steps = [
    { label: 'Assigned', field: 'assigntime' }, { label: 'Accepted', field: 'starttime' }, { label: 'Arrived', field: 'arrivaltime' },
    { label: 'Picked', field: 'pickuptime' }, { label: 'Delivered', field: 'deliverytime' },
  ];

  // Portal to <body> so `fixed inset-0` is viewport-relative even when an ancestor
  // in the view tree is transformed/blurred (otherwise the panel collapses).
  return createPortal(
    <div className="fixed inset-0 z-[200] flex items-center justify-center p-4" style={{ background: 'rgba(15,23,42,0.4)', backdropFilter: 'blur(4px)' }} onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="bg-white max-h-[90vh] flex flex-col overflow-hidden animate-in zoom-in-95 duration-200" style={{ width: 'min(32rem, 92vw)', border: `1px solid ${BORDER}`, boxShadow: '0 18px 50px rgba(15,23,42,0.18)' }}>
        <div style={{ height: 4, background: `linear-gradient(90deg, ${BRAND} 0%, ${BRAND_LIGHT} 100%)` }} />
        <div className="p-4 border-b flex justify-between items-center shrink-0" style={{ borderColor: BORDER, background: SURFACE_ALT }}>
          <h4 className="font-extrabold flex items-center gap-2" style={{ color: TEXT }}><Truck size={16} style={{ color: BRAND }} /> {fstr(row.orderid) || `Delivery ${fstr(row.deliveryid)}`}</h4>
          <button onClick={onClose} className="p-1 rounded-full cursor-pointer" style={{ color: TEXT_3 }}><X size={16} /></button>
        </div>
        <div className="p-4 space-y-4 overflow-y-auto flex-1">
          <div className="flex items-center justify-between">
            <StatusChip label={st || '—'} color={statusColor(DELIVERY_STATUS, st)} />
            <span className="inline-flex items-center gap-1.5 text-[11px] font-medium" style={{ color: TEXT_2 }}><UserCheck size={12} /> {rider || 'Unassigned'}</span>
          </div>
          <div className="p-3 rounded-xl space-y-1.5" style={{ background: SURFACE_ALT, border: `1px solid ${BORDER}` }}>
            <div className="font-bold" style={{ color: TEXT }}>{fstr(row.deliverycustomer) || fstr(row.deliverycontactno) || 'Customer'}</div>
            {fstr(row.deliverycontactno) && <div className="flex items-center gap-2 font-mono text-xs" style={{ color: TEXT_2 }}><Phone size={12} /> {fstr(row.deliverycontactno)}</div>}
            <div className="flex items-start gap-2 text-xs" style={{ color: TEXT_2 }}><MapPin size={12} className="mt-0.5 shrink-0" /> <span className="leading-relaxed">{fstr(row.deliveryaddress) || fstr(row.deliverylocation) || fstr(row.deliverysuburb) || 'Address unavailable'}</span></div>
          </div>
          <div>
            <span className="text-[10px] font-extrabold uppercase tracking-wide block mb-2" style={{ color: TEXT_2 }}>Delivery Timeline</span>
            <div className="space-y-2.5 pl-1">
              {steps.map((s) => {
                const ts = fstr(row[s.field]); const done = Boolean(ts);
                return (
                  <div key={s.field} className="flex items-center gap-2.5">
                    <CheckCircle2 size={13} style={{ color: done ? '#10b981' : '#cbd5e1' }} />
                    <span className="font-semibold text-xs" style={{ color: done ? TEXT : TEXT_3 }}>{s.label}</span>
                    <span className="ml-auto text-[10px] font-mono" style={{ color: TEXT_3 }}>{done ? shortTime(ts) : '—'}</span>
                  </div>
                );
              })}
            </div>
          </div>
          <div>
            <span className="text-[10px] font-extrabold uppercase tracking-wide mb-2 flex items-center gap-1.5" style={{ color: TEXT_2 }}><Package size={12} /> Items</span>
            <div className="rounded-xl p-3" style={{ background: 'rgba(248,250,252,0.6)', border: `1px solid ${BORDER}` }}>
              {detailsQ.isLoading && <div className="py-2 flex items-center gap-1.5 text-[11px] font-medium" style={{ color: TEXT_3 }}><Loader2 size={12} className="animate-spin" /> Loading items…</div>}
              {!detailsQ.isLoading && lines.length === 0 && <div className="py-2 text-[11px] font-medium" style={{ color: TEXT_3 }}>No line items returned.</div>}
              {lines.map((item, idx) => (
                <div key={idx} className="py-2 flex justify-between items-center" style={{ borderTop: idx ? `1px solid ${DIVIDER}` : undefined }}>
                  <div><p className="font-bold text-xs" style={{ color: TEXT }}>{item.name}</p><p className="text-[10px]" style={{ color: TEXT_2 }}>Qty: {item.quantity} × ₹{item.price}</p></div>
                  <span className="font-extrabold font-mono text-xs" style={{ color: TEXT }}>₹{item.lineTotal.toLocaleString('en-IN')}</span>
                </div>
              ))}
            </div>
          </div>
          <RiderActions row={row} riders={riders} />
        </div>
        <div className="p-3 border-t flex justify-end shrink-0" style={{ borderColor: BORDER, background: SURFACE_ALT }}>
          <button onClick={onClose} className="rounded-full font-bold cursor-pointer text-white" style={{ padding: '8px 16px', background: `linear-gradient(135deg, ${BRAND}, ${BRAND_LIGHT})` }}>Close</button>
        </div>
      </div>
    </div>,
    document.body,
  );
}
