"use client";

import { useEffect, useState } from "react";

import { CheckCircle2, Clock, GripVertical, MapPin, Package, Truck, UserCheck } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Sheet, SheetContent } from "@/components/ui/sheet";
import { OrderTicket } from "@/components/order-ticket/order-ticket";
import { StageBadge } from "@/components/order-ticket/stage-badge";
import { useShallow } from "zustand/react/shallow";

import { type AuthUser, getAuthUser } from "@/lib/auth";
import { useT } from "@/lib/i18n";
import { useLanguage } from "@/lib/language-context";
import type { Driver, Order } from "@/lib/order/types";
import { useOrdersStore } from "@/stores/orders/orders-store";
import { useRef } from "react";

export default function DispatchPage() {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const t = useT();

  const { orders, drivers, assignDriver, transition, driverRunOrder, setDriverRunOrder } = useOrdersStore(
    useShallow((s) => ({
      orders: s.orders,
      drivers: s.drivers,
      assignDriver: s.assignDriver,
      transition: s.transition,
      driverRunOrder: s.driverRunOrder,
      setDriverRunOrder: s.setDriverRunOrder,
    })),
  );

  useEffect(() => {
    setUser(getAuthUser());
  }, []);

  const selectedOrder = orders.find((o) => o.id === selectedId);

  // Orders awaiting assignment (ready, delivery only)
  const awaitingAssignment = orders.filter(
    (o) => o.type === "delivery" && o.stage === "ready",
  );

  // Orders assigned but not yet out
  const assignedOrders = orders.filter(
    (o) => o.type === "delivery" && (o.stage === "assigned" || o.stage === "out_for_delivery"),
  );

  // Collection orders that are ready
  const collectionReady = orders.filter(
    (o) => o.type === "collection" && o.stage === "ready",
  );

  const driverLoads: Record<string, Order[]> = {};
  for (const d of drivers) {
    driverLoads[d.id] = assignedOrders.filter((o) => o.driverId === d.id);
  }

  const handleAssignAndDispatch = (orderId: string, driverId: string) => {
    assignDriver(orderId, driverId);
    setTimeout(() => transition(orderId, "assigned"), 50);
  };

  const handleCollectionHandover = (orderId: string) => {
    // Collection: ready → assigned → completed (customer collected in-store)
    transition(orderId, "assigned");
    setTimeout(() => transition(orderId, "completed"), 100);
  };

  return (
    <div className="flex h-full flex-col gap-4">
      <div>
        <h1 className="font-bold text-xl">{t.dispatch_panel}</h1>
        <p className="text-muted-foreground text-sm">
          {awaitingAssignment.length} awaiting driver · {assignedOrders.length} on the road
        </p>
      </div>

      <div className="grid flex-1 grid-cols-1 gap-4 overflow-auto lg:grid-cols-3">
        {/* Awaiting assignment */}
        <div className="flex flex-col gap-2">
          <div>
            <h2 className="flex items-center gap-2 font-semibold text-sm">
              <span className="size-2 rounded-full bg-orange-400" />
              {t.dispatch_awaiting}
              <span className="ml-auto rounded-full bg-orange-100 px-2 py-0.5 text-xs font-bold text-orange-700 dark:bg-orange-900/30 dark:text-orange-400">
                {awaitingAssignment.length}
              </span>
            </h2>
            <p className="text-[11px] text-muted-foreground mt-0.5">
              {t.dispatch_awaiting_sub}
            </p>
          </div>
          {awaitingAssignment.length === 0 && <EmptySlot label={t.dispatch_no_awaiting} />}
          {awaitingAssignment.map((order) => (
            <DispatchCard
              key={order.id}
              order={order}
              drivers={drivers}
              isSelected={selectedId === order.id}
              onOpen={() => setSelectedId(order.id)}
              onAssign={(driverId) => handleAssignAndDispatch(order.id, driverId)}
            />
          ))}
        </div>

        {/* Collection ready */}
        <div className="flex flex-col gap-2">
          <div>
            <h2 className="flex items-center gap-2 font-semibold text-sm">
              <span className="size-2 rounded-full bg-green-500" />
              {t.dispatch_collection}
              <span className="ml-auto rounded-full bg-green-100 px-2 py-0.5 text-xs font-bold text-green-700 dark:bg-green-900/30 dark:text-green-400">
                {collectionReady.length}
              </span>
            </h2>
            <p className="text-[11px] text-muted-foreground mt-0.5">
              {t.dispatch_collection_sub}
            </p>
          </div>
          {collectionReady.length === 0 && <EmptySlot label={t.dispatch_no_collections} />}
          {collectionReady.map((order) => (
            <CollectionReadyCard
              key={order.id}
              order={order}
              isSelected={selectedId === order.id}
              onOpen={() => setSelectedId(order.id)}
              onComplete={() => handleCollectionHandover(order.id)}
            />
          ))}
        </div>

        {/* Drivers + their runs */}
        <div className="flex flex-col gap-3">
          <h2 className="flex items-center gap-2 font-semibold text-sm">
            <span className="size-2 rounded-full bg-violet-500" />
            {t.dispatch_drivers}
          </h2>
          {drivers.map((driver) => (
            <DriverRunCard
              key={driver.id}
              driver={driver}
              load={driverLoads[driver.id] ?? []}
              runOrder={driverRunOrder[driver.id]}
              onReorder={(ids) => setDriverRunOrder(driver.id, ids)}
              onOpen={setSelectedId}
            />
          ))}
        </div>
      </div>

      <Sheet open={!!selectedOrder} onOpenChange={(open) => { if (!open) setSelectedId(null); }}>
        <SheetContent side="right" className="w-full w-[440px] max-w-[92vw] p-0 overflow-hidden flex flex-col">
          {selectedOrder && user && (
            <OrderTicket
              order={selectedOrder}
              role={user.role}
              onNew={() => setSelectedId(null)}
              onClose={() => setSelectedId(null)}
            />
          )}
        </SheetContent>
      </Sheet>
    </div>
  );
}

function DispatchCard({
  order,
  drivers,
  isSelected,
  onOpen,
  onAssign,
}: {
  order: Order;
  drivers: Driver[];
  isSelected: boolean;
  onOpen: () => void;
  onAssign: (driverId: string) => void;
}) {
  const { lang } = useLanguage();
  const requestedTime = order.requestedAt
    ? new Date(order.requestedAt).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" })
    : null;

  return (
    <div
      className={`rounded-lg border bg-card p-3 transition-all ${isSelected ? "border-primary ring-1 ring-primary/30" : ""}`}
    >
      <button type="button" onClick={onOpen} className="w-full text-left">
        <div className="flex items-center justify-between gap-2">
          <span className="font-mono font-bold text-xs">{order.id}</span>
          {requestedTime && (
            <div className="flex items-center gap-1 text-muted-foreground text-[11px]">
              <Clock className="size-3" />
              {requestedTime}
            </div>
          )}
        </div>
        <p className="mt-0.5 font-semibold text-sm">{order.customer.na}</p>
        {order.address && (
          <div className="mt-0.5 flex items-center gap-1 text-muted-foreground text-[12px]">
            <MapPin className="size-3 shrink-0" />
            <span className="truncate">{order.address.ad}</span>
            {order.address.miles && (
              <span className="shrink-0 text-[11px]">{order.address.miles} mi</span>
            )}
          </div>
        )}
        <p className="mt-1 truncate text-muted-foreground text-[11px]">
          {order.items.map((i) => `${lang === "zh" ? i.chineseName : i.description}×${i.qty}`).join(" · ")}
        </p>
      </button>

      <div className="mt-2 flex items-center gap-2">
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="outline" size="sm" className="h-7 flex-1 gap-1 text-xs">
              <UserCheck className="size-3.5" />
              {order.driverId
                ? drivers.find((d) => d.id === order.driverId)?.name ?? "Assigned"
                : "Assign & Dispatch"}
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="start">
            {drivers.map((d) => (
              <DropdownMenuItem key={d.id} onClick={() => onAssign(d.id)} className="gap-2">
                {d.id === order.driverId && <CheckCircle2 className="size-3.5 text-primary" />}
                {d.id !== order.driverId && <span className="size-3.5" />}
                {d.name}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </div>
  );
}

function CollectionReadyCard({
  order,
  isSelected,
  onOpen,
  onComplete,
}: {
  order: Order;
  isSelected: boolean;
  onOpen: () => void;
  onComplete: () => void;
}) {
  const { lang } = useLanguage();
  const t = useT();
  return (
    <div
      className={`rounded-lg border bg-card p-3 transition-all ${isSelected ? "border-primary ring-1 ring-primary/30" : ""}`}
    >
      <button type="button" onClick={onOpen} className="w-full text-left">
        <span className="font-mono font-bold text-xs">{order.id}</span>
        <p className="mt-0.5 font-semibold text-sm">{order.customer.na}</p>
        <p className="mt-1 truncate text-muted-foreground text-[11px]">
          {order.items.map((i) => `${lang === "zh" ? i.chineseName : i.description}×${i.qty}`).join(" · ")}
        </p>
      </button>
      <Button
        variant="default"
        size="sm"
        className="mt-2 h-7 w-full gap-1 text-xs bg-green-600 hover:bg-green-700 text-white"
        onClick={onComplete}
      >
        <CheckCircle2 className="size-3.5" />
        {t.dispatch_collected}
      </Button>
    </div>
  );
}

function DriverRunCard({
  driver,
  load,
  runOrder,
  onReorder,
  onOpen,
}: {
  driver: Driver;
  load: Order[];
  runOrder?: string[];
  onReorder: (ids: string[]) => void;
  onOpen: (id: string) => void;
}) {
  const dragIdx = useRef<number | null>(null);
  const t = useT();

  // Apply FOH sequence if set, otherwise natural order
  const orderedLoad = runOrder
    ? [...load].sort((a, b) => {
        const ai = runOrder.indexOf(a.id);
        const bi = runOrder.indexOf(b.id);
        return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
      })
    : load;

  const deliveryMiles = orderedLoad.reduce((acc, o) => acc + (o.address?.miles ?? 0), 0);
  const returnMiles = orderedLoad.length > 0 ? (orderedLoad[orderedLoad.length - 1]?.address?.miles ?? 0) : 0;
  const roundTripMiles = deliveryMiles + returnMiles;

  const handleDragStart = (idx: number) => { dragIdx.current = idx; };
  const handleDragOver = (e: React.DragEvent, idx: number) => {
    e.preventDefault();
    if (dragIdx.current === null || dragIdx.current === idx) return;
    const reordered = [...orderedLoad];
    const [moved] = reordered.splice(dragIdx.current, 1);
    reordered.splice(idx, 0, moved);
    dragIdx.current = idx;
    onReorder(reordered.map((o) => o.id));
  };

  return (
    <div className="rounded-lg border bg-card p-3">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Truck className="size-4 text-muted-foreground" />
          <span className="font-medium text-sm">{driver.name}</span>
        </div>
        <span className="text-muted-foreground text-xs">{load.length} order{load.length !== 1 ? "s" : ""}</span>
      </div>

      {orderedLoad.length > 0 && (
        <div className="mt-1.5 rounded bg-violet-50 dark:bg-violet-950/30 px-2 py-1 text-[11px]">
          <div className="flex items-center justify-between">
            <span className="text-violet-700 dark:text-violet-300 font-medium">Round-trip miles</span>
            <span className="font-bold text-violet-800 dark:text-violet-200">{roundTripMiles.toFixed(1)} mi</span>
          </div>
          <div className="text-violet-500/80 dark:text-violet-400/70 text-[10px]">
            delivery {deliveryMiles.toFixed(1)} mi + return {returnMiles.toFixed(1)} mi
          </div>
        </div>
      )}

      {orderedLoad.length > 0 && (
        <div className="mt-2 space-y-1">
          {orderedLoad.length > 1 && (
            <p className="text-[10px] text-muted-foreground mb-1 flex items-center gap-1">
              <GripVertical className="size-3" /> {t.dispatch_drag_hint}
            </p>
          )}
          {orderedLoad.map((o, idx) => (
            <div
              key={o.id}
              draggable
              onDragStart={() => handleDragStart(idx)}
              onDragOver={(e) => handleDragOver(e, idx)}
              className="flex w-full items-center gap-2 rounded border bg-muted/30 px-2 py-1.5 text-xs cursor-grab active:cursor-grabbing hover:bg-muted/60 select-none"
            >
              <GripVertical className="size-3.5 text-muted-foreground shrink-0" />
              <span className="font-medium text-muted-foreground w-4 shrink-0">#{idx + 1}</span>
              <button
                type="button"
                onClick={() => onOpen(o.id)}
                className="font-mono hover:text-primary"
              >
                {o.id}
              </button>
              <span className="flex-1 truncate">{o.customer.na}</span>
              {o.address?.miles && (
                <span className="text-[10px] text-muted-foreground shrink-0">{o.address.miles} mi</span>
              )}
              <StageBadge stage={o.stage} type={o.type} />
            </div>
          ))}
        </div>
      )}
      {orderedLoad.length === 0 && (
        <p className="mt-1.5 text-muted-foreground text-xs">No active orders</p>
      )}
    </div>
  );
}

function EmptySlot({ label }: { label: string }) {
  return (
    <div className="flex flex-col items-center justify-center rounded-lg border border-dashed py-8 text-muted-foreground">
      <Package className="size-8 mb-2 opacity-30" />
      <p className="text-xs">{label}</p>
    </div>
  );
}
