"use client";

import * as React from "react";
import {
  ChevronDownIcon,
  CircleIcon,
  CloudOffIcon,
  FileBarChartIcon,
  KeyboardIcon,
  LockIcon,
  PauseIcon,
  PlayIcon,
  UserRoundCogIcon,
  VaultIcon,
  WifiIcon,
} from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Kbd } from "@/components/ui/kbd";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";

import { SidebarLogo } from "./sidebar-logo";
import { TONE_BOX } from "./tones";

export type TillShortcut = "pay" | "hold" | "search" | "customer" | "quantity" | "drawer" | "complete" | "clear";

/** The till's keyboard map. Function keys, so they never collide with typing in the search box. */
export const TILL_SHORTCUTS: { key: string; code: string; action: TillShortcut; label: string }[] = [
  { key: "F1", code: "F1", action: "pay", label: "Pay" },
  { key: "F2", code: "F2", action: "hold", label: "Hold sale" },
  { key: "F3", code: "F3", action: "search", label: "Search products" },
  { key: "F4", code: "F4", action: "customer", label: "Choose customer" },
  { key: "F5", code: "F5", action: "quantity", label: "Change quantity of the selected line" },
  { key: "F8", code: "F8", action: "drawer", label: "Open cash drawer" },
  { key: "F12", code: "F12", action: "complete", label: "Complete sale (once payment covers the total)" },
  { key: "Esc", code: "Escape", action: "clear", label: "Clear search" },
];

export type PosShift =
  | { status: "open"; openedAt: Date; float: number }
  | { status: "closing"; openedAt: Date; float: number }
  | { status: "none" };

export type PosBarProps = {
  till: string;
  branch: string;
  cashier: { name: string; role: string };
  shift: PosShift;
  drawer?: "closed" | "open";
  /** Sales recorded while offline and waiting to sync. */
  online?: boolean;
  queued?: number;
  held?: number;
  tone?: "light" | "brand";
  onOpenShift?: () => void;
  onCloseShift?: () => void;
  onHeld?: () => void;
  onLock?: () => void;
  onSwitchCashier?: () => void;
  /** When set, the bar listens for the till shortcuts (F1–F5, F8, F12, Esc) and reports them. */
  onShortcut?: (a: TillShortcut) => void;
  className?: string;
};

const hhmm = (d: Date) => d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });

function duration(from: Date, now: number) {
  const mins = Math.max(0, Math.floor((now - from.getTime()) / 60000));
  const h = Math.floor(mins / 60);
  return h ? `${h} h ${String(mins % 60).padStart(2, "0")} min` : `${mins} min`;
}

/**
 * Current time rounded to the minute, refreshed each minute, so the shift duration stays honest without
 * re-rendering every second. Null on the server: the time differs there, and rendering it would mismatch.
 */
const minuteNow = () => Math.floor(Date.now() / 60_000) * 60_000;
function subscribeMinute(cb: () => void) {
  const t = setInterval(cb, 15_000);
  return () => clearInterval(t);
}
function useMinuteClock(): number | null {
  return React.useSyncExternalStore(subscribeMinute, minuteNow, () => null);
}

function Pill({ tone, children, className }: { tone: "success" | "warning" | "error" | "neutral"; children: React.ReactNode; className?: string }) {
  return <span className={cn("inline-flex h-7 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium whitespace-nowrap", TONE_BOX[tone], className)}>{children}</span>;
}

/**
 * POS bar: the top strip of the full-screen till. Shows which till and branch, who is selling, whether a shift
 * is open (and since when), the connection and cash-drawer state, held sales, and the keyboard map.
 * With no shift open the bar says so and offers Open shift, because a till without a shift cannot sell.
 */
export function PosBar({
  till,
  branch,
  cashier,
  shift,
  drawer = "closed",
  online = true,
  queued = 0,
  held = 0,
  tone = "light",
  onOpenShift,
  onCloseShift,
  onHeld,
  onLock,
  onSwitchCashier,
  onShortcut,
  className,
}: PosBarProps) {
  const now = useMinuteClock();
  const brand = tone === "brand";

  React.useEffect(() => {
    if (!onShortcut) return;
    const onKey = (e: KeyboardEvent) => {
      const s = TILL_SHORTCUTS.find((x) => x.code === e.key);
      if (!s) return;
      // Esc belongs to open dialogs and menus first.
      if (s.action === "clear" && document.querySelector('[role="dialog"],[role="menu"]')) return;
      e.preventDefault();
      onShortcut(s.action);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onShortcut]);

  const initials = cashier.name
    .split(" ")
    .map((p) => p[0])
    .slice(0, 2)
    .join("");

  const ghost = brand ? "text-white hover:bg-white/10 hover:text-white aria-expanded:bg-white/10" : "";

  return (
    <header
      aria-label="Till status"
      className={cn(
        "@container flex h-14 shrink-0 items-center gap-2 border-b px-3 @2xl:gap-3",
        brand ? "border-[var(--mdr-teal-800)] bg-[var(--mdr-teal-700)] text-white" : "border-border bg-card text-foreground",
        className,
      )}
    >
      {/* Till and branch */}
      <div className="flex max-w-56 shrink-0 items-center gap-2.5">
        <SidebarLogo tone={tone} symbol />
        <div className="min-w-0 leading-tight">
          <p className="truncate text-sm font-semibold">{till}</p>
          <p className={cn("truncate text-xs", brand ? "text-white/70" : "text-muted-foreground")}>{branch}</p>
        </div>
      </div>

      <span className={cn("h-7 w-px shrink-0", brand ? "bg-white/20" : "bg-border")} aria-hidden />

      {/* Shift */}
      {shift.status === "none" ? (
        <div className="flex items-center gap-2">
          <Pill tone="warning">
            <CircleIcon className="size-2 fill-current" aria-hidden />
            No shift open
          </Pill>
          <Button size="sm" onClick={onOpenShift} className={brand ? "bg-white text-[var(--mdr-teal-800)] hover:bg-white/90" : undefined}>
            <PlayIcon data-icon="inline-start" />
            Open shift
          </Button>
        </div>
      ) : (
        <Pill tone={shift.status === "open" ? "success" : "warning"}>
          <CircleIcon className="size-2 fill-current" aria-hidden />
          {shift.status === "open" ? "Shift open" : "Closing shift"}
          {now !== null ? (
            <span className="hidden font-normal opacity-90 @3xl:inline">
              since {hhmm(shift.openedAt)} · {duration(shift.openedAt, now)}
            </span>
          ) : null}
        </Pill>
      )}

      {/* Connection and drawer */}
      <div className="flex items-center gap-2">
        {online ? (
          <span className={cn("hidden items-center gap-1.5 text-xs whitespace-nowrap @4xl:inline-flex", brand ? "text-white/80" : "text-muted-foreground")}>
            <WifiIcon className="size-3.5" aria-hidden />
            Online{queued ? ` · syncing ${queued}` : ""}
          </span>
        ) : (
          <Pill tone="warning">
            <CloudOffIcon className="size-3.5" aria-hidden />
            Offline
            {queued ? (
              <>
                {" "}
                · {queued}
                <span className="hidden @3xl:inline"> {queued === 1 ? "sale" : "sales"} queued</span>
              </>
            ) : null}
          </Pill>
        )}
        {drawer === "open" ? (
          <Pill tone="warning">
            <VaultIcon className="size-3.5" aria-hidden />
            Drawer open
          </Pill>
        ) : (
          <span className={cn("hidden items-center gap-1.5 text-xs whitespace-nowrap @4xl:inline-flex", brand ? "text-white/80" : "text-muted-foreground")}>
            <VaultIcon className="size-3.5" aria-hidden />
            Drawer closed
          </span>
        )}
      </div>

      {/* Actions */}
      <div className="ml-auto flex items-center gap-1">
        <Button variant="ghost" size="sm" className={ghost} onClick={onHeld} disabled={shift.status === "none"} aria-label={`Held sales: ${held}`}>
          <PauseIcon data-icon="inline-start" />
          <span className="hidden @3xl:inline">Held</span>
          {held ? (
            <Badge className={cn("ml-0.5 h-4.5 min-w-4.5 rounded-full px-1 tabular-nums", brand ? "bg-white text-[var(--mdr-teal-800)]" : "")}>{held}</Badge>
          ) : null}
        </Button>

        <Popover>
          <PopoverTrigger render={<Button variant="ghost" size="icon-sm" className={ghost} aria-label="Keyboard shortcuts" />}>
            <KeyboardIcon />
          </PopoverTrigger>
          <PopoverContent align="end" className="w-60 p-3">
            <p className="mb-2 text-sm font-semibold">Till shortcuts</p>
            <ul className="space-y-1.5">
              {TILL_SHORTCUTS.map((s) => (
                <li key={s.key} className="flex items-center justify-between text-sm">
                  <span className="text-muted-foreground">{s.label}</span>
                  <Kbd>{s.key}</Kbd>
                </li>
              ))}
            </ul>
          </PopoverContent>
        </Popover>

        <Button variant="ghost" size="icon-sm" className={ghost} aria-label="Lock till" title="Lock till (cashier PIN to unlock)" onClick={onLock}>
          <LockIcon />
        </Button>

        <DropdownMenu>
          <DropdownMenuTrigger
            render={<Button variant="ghost" className={cn("h-10 gap-2 px-1.5", ghost)} aria-label={`Cashier ${cashier.name}, ${cashier.role}`} />}
          >
            <span
              className={cn("flex size-8 items-center justify-center rounded-full text-xs font-semibold", brand ? "bg-white/15 text-white" : "bg-accent text-accent-foreground")}
              aria-hidden
            >
              {initials}
            </span>
            <span className="hidden text-left leading-tight @3xl:block">
              <span className="block text-sm font-medium">{cashier.name}</span>
              <span className={cn("block text-xs", brand ? "text-white/70" : "text-muted-foreground")}>{cashier.role}</span>
            </span>
            <ChevronDownIcon className="size-4 opacity-70" />
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-56">
            <DropdownMenuGroup>
              <DropdownMenuLabel>
                {cashier.name} · {till}
              </DropdownMenuLabel>
              <DropdownMenuItem onClick={onSwitchCashier}>
                <UserRoundCogIcon /> Switch cashier
              </DropdownMenuItem>
              <DropdownMenuItem onClick={onLock}>
                <LockIcon /> Lock till
              </DropdownMenuItem>
            </DropdownMenuGroup>
            {shift.status !== "none" ? (
              <>
                <DropdownMenuSeparator />
                <DropdownMenuGroup>
                  <DropdownMenuItem onClick={onCloseShift}>
                    <FileBarChartIcon /> Close shift (Z-report)
                  </DropdownMenuItem>
                </DropdownMenuGroup>
              </>
            ) : null}
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </header>
  );
}
