import { useEffect } from 'react';
import { Card } from '@astryxdesign/core/Card';
import { HStack } from '@astryxdesign/core/HStack';
import { Text } from '@astryxdesign/core/Text';
import { VStack } from '@astryxdesign/core/VStack';
import { Bike, Check, MapPin, Phone, X } from 'lucide-react';
import type { DeliveryRow, OrderRow } from '@/api/types';
import { branchLabel, moneyExact } from './format';
import { DELIVERY_STATUS, ORDER_STATUS, orderQuantity, orderValue, statusColor } from './orderStatus';
type Row = OrderRow | DeliveryRow;
export type RowKind = 'order' | 'delivery';
/**
* The five stages an order walks, taken from the old console verbatim.
*
* The middle one matters and is easy to drop: **Packed & Ready** sits between
* confirmation and pickup, and it is the stage where an order stalls when a
* shop is busy. A four-step timeline that jumps from Confirmed to Out for
* Delivery hides exactly the delay an operator is trying to find.
*/
const STEPS: { label: string; fields: string[] }[] = [
// A delivery job has no `orderdate` of its own — its clock starts at
// `deliverydate`. Falling back keeps the first step from reading as a missing
// stamp on every delivery ever opened.
{ label: 'Order placed', fields: ['orderdate', 'deliverydate'] },
{ label: 'Confirmed', fields: ['starttime', 'assigntime'] },
{ label: 'Packed & ready', fields: ['packtime', 'arrivaltime'] },
{ label: 'Out for delivery', fields: ['pickuptime'] },
{ label: 'Delivered', fields: ['deliverytime'] },
];
/**
* One order or delivery, in full.
*
* A right-hand sheet rather than a modal: the operator is comparing this row
* against the list behind it — "is this the one that stalled?" — and a modal
* that greys the list out removes the thing being compared against.
*/
export function OrderDetailDrawer({
row,
kind,
onClose,
}: {
row: Row;
kind: RowKind;
onClose: () => void;
}) {
const delivery = kind === 'delivery';
// Narrowed once, here. `kind` comes from the table the row was clicked in, so
// it is authoritative in a way that sniffing fields is not — a delivery row
// carries an `orderheaderid` too, which is what made the first attempt at
// this discriminator silently mis-classify every delivery.
const job = delivery ? (row as DeliveryRow) : undefined;
const order = delivery ? undefined : (row as OrderRow);
// Escape closes. A dialog that can only be dismissed by finding the scrim
// with a mouse is not dismissible for anyone on a keyboard, and this one sits
// over the list an operator is working through.
useEffect(() => {
function onKeyDown(event: KeyboardEvent) {
if (event.key === 'Escape') onClose();
}
window.addEventListener('keydown', onKeyDown);
return () => window.removeEventListener('keydown', onKeyDown);
}, [onClose]);
const title = row.orderid || (job ? `DLV-${job.deliveryid}` : `#${order?.orderheaderid}`);
const status = row.orderstatus;
const colour = statusColor(delivery ? DELIVERY_STATUS : ORDER_STATUS, status);
const value = job ? (job.deliveryamt ?? 0) : orderValue(row);
const cancelled = (status ?? '').toLowerCase().includes('cancel');
return (