"use client";

import * as React from "react";
import { CircleCheckIcon, ClockIcon, TriangleAlertIcon, XIcon } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Spinner } from "@/components/ui/spinner";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";
import { daysBetween, formatDate, localToday } from "@/lib/format";
import type { Batch } from "@/lib/mock-data";
import { cn } from "@/lib/utils";

import { NumberInput } from "./money";
import { TONE_BOX, TONE_FILL, TONE_TEXT, type Tone } from "./tones";

/* ------------------------------ Batch / expiry chip ----------------------------- */

export function expiryTone(daysLeft: number): Tone {
  if (daysLeft < 0) return "error";
  if (daysLeft < 30) return "error";
  if (daysLeft < 90) return "warning";
  return "success";
}

/** Days-left chip. Expired and under 30 days are error, under 90 warning, otherwise ok. Label always carries the meaning. */
export function BatchChip({ expiryDate, today = localToday(), className }: { expiryDate: string; today?: string; className?: string }) {
  const days = daysBetween(today, expiryDate);
  const tone = expiryTone(days);
  const label = days < 0 ? `Expired ${-days}d ago` : days === 0 ? "Expires today" : `${days}d left`;
  const Icon = days < 0 ? XIcon : days < 90 ? TriangleAlertIcon : CircleCheckIcon;
  return (
    <Badge variant="outline" className={cn("rounded-md tabular-nums", TONE_BOX[tone], className)} title={`Expiry ${formatDate(expiryDate)}`}>
      <Icon />
      {label}
    </Badge>
  );
}

/* ------------------------------- Stock level ------------------------------------ */

/** Bar plus count against the reorder level. The marker shows where reorder sits (at 50% of the bar scale). */
export function StockLevel({ stock, minStock, className }: { stock: number; minStock: number; className?: string }) {
  const scale = Math.max(minStock * 2, stock, 1);
  const pct = Math.min(100, (stock / scale) * 100);
  const tone: Tone = stock === 0 ? "error" : stock <= minStock ? "warning" : "success";
  const label = stock === 0 ? "Out of stock" : stock <= minStock ? "Low stock" : "In stock";
  return (
    <div className={cn("w-full min-w-40 space-y-1", className)}>
      <div className="flex items-baseline justify-between text-xs">
        <span className={cn("font-medium", TONE_TEXT[tone])}>{label}</span>
        <span className="tabular-nums text-muted-foreground">
          <span className="font-medium text-foreground">{stock}</span> / reorder at {minStock}
        </span>
      </div>
      <div className="relative h-2 overflow-hidden rounded-sm bg-muted" role="meter" aria-valuenow={stock} aria-valuemin={0} aria-valuemax={scale} aria-label={`${stock} units, reorder level ${minStock}`}>
        <div className={cn("h-full", TONE_FILL[tone])} style={{ width: `${pct}%` }} />
        <div className="absolute inset-y-0 w-px bg-foreground" style={{ left: `${(minStock / scale) * 100}%` }} />
      </div>
    </div>
  );
}

/* ---------------------------- Stock adjustment form ----------------------------- */

export const ADJUSTMENT_REASONS = ["Stock count correction", "Damaged", "Expired write-off", "Theft or loss", "Returned to supplier", "Opening stock"];
const REASONS = ADJUSTMENT_REASONS;

export type StockAdjustment = { direction: "add" | "remove"; quantity: number; reason: string; note: string };

/**
 * `onSubmit` (card 009): a live page receives what was entered and saves it. Without it (the demo),
 * the form only shows its states, as before. A quantity of 0 shows the error state instead of submitting.
 */
export function StockAdjustmentForm({
  productName,
  currentStock,
  state = "default",
  errorMessage,
  onSubmit,
}: {
  productName: string;
  currentStock: number;
  state?: "default" | "loading" | "error" | "disabled";
  errorMessage?: string;
  onSubmit?: (adjustment: StockAdjustment) => void;
}) {
  const [direction, setDirection] = React.useState<"add" | "remove">("remove");
  const [qty, setQty] = React.useState(0);
  const [reason, setReason] = React.useState(REASONS[0]);
  const [note, setNote] = React.useState("");
  const [tried, setTried] = React.useState(false);
  const disabled = state === "disabled" || state === "loading";
  const after = Math.max(0, currentStock + (direction === "add" ? qty : -qty));
  const invalid = state === "error" || (tried && qty <= 0);
  return (
    <form
      className="w-full max-w-sm space-y-3"
      onSubmit={(e) => {
        e.preventDefault();
        if (!onSubmit) return;
        setTried(true);
        if (qty > 0) onSubmit({ direction, quantity: qty, reason, note: note.trim() });
      }}
      aria-busy={state === "loading"}
    >
      <div className="flex items-baseline justify-between">
        <h3 className="text-sm font-semibold">Adjust stock</h3>
        <span className="text-xs text-muted-foreground">
          {productName}, <span className="tabular-nums">{currentStock}</span> on hand
        </span>
      </div>
      <Field>
        <FieldLabel>Reason</FieldLabel>
        <Select value={reason} onValueChange={(v) => v && setReason(String(v))} disabled={disabled}>
          <SelectTrigger className="w-full" aria-invalid={invalid || undefined}>
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {REASONS.map((r) => (
              <SelectItem key={r} value={r}>
                {r}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </Field>
      <div className="grid grid-cols-2 gap-3">
        <Field>
          <FieldLabel>Direction</FieldLabel>
          <div className="grid grid-cols-2 gap-1 rounded-lg border border-border p-0.5" role="group" aria-label="Direction">
            {(["add", "remove"] as const).map((d) => (
              <Button key={d} type="button" size="sm" variant={direction === d ? "default" : "ghost"} disabled={disabled} aria-pressed={direction === d} onClick={() => setDirection(d)}>
                {d === "add" ? "Add" : "Remove"}
              </Button>
            ))}
          </div>
        </Field>
        <Field>
          <FieldLabel>Quantity</FieldLabel>
          <div onChange={(e) => setQty(Number((e.target as HTMLInputElement).value.replace(/\D/g, "")) || 0)}>
            <NumberInput aria-label="Quantity" min={0} unit="units" disabled={disabled} invalid={invalid} defaultValue={state === "error" ? 0 : null} />
          </div>
        </Field>
      </div>
      <Field>
        <FieldLabel>Note</FieldLabel>
        <Textarea rows={2} placeholder="Optional. Shows in the audit trail." disabled={disabled} value={note} onChange={(e) => setNote(e.target.value)} />
      </Field>
      {invalid ? <FieldError>{errorMessage ?? "Enter a quantity greater than zero."}</FieldError> : null}
      <div className="flex items-center justify-between border-t border-border pt-3">
        <span className="text-xs text-muted-foreground tabular-nums">
          New level <span className="font-medium text-foreground">{after}</span>
        </span>
        <Button type="submit" disabled={disabled}>
          {state === "loading" ? <Spinner /> : null}
          {state === "loading" ? "Saving" : "Save adjustment"}
        </Button>
      </div>
    </form>
  );
}

/* ------------------------------- Batch table ------------------------------------ */

/** Batches of one product sorted by expiry (FEFO). The first batch with stock is marked as the next to be sold. */
export function BatchTable({ batches, today = localToday() }: { batches: Batch[]; today?: string }) {
  const sorted = [...batches].sort((a, b) => (a.expiryDate < b.expiryDate ? -1 : a.expiryDate > b.expiryDate ? 1 : a.id - b.id));
  const nextId = sorted.find((b) => b.stock > 0)?.id;
  if (sorted.length === 0) {
    return <p className="p-6 text-center text-sm text-muted-foreground">No batches received yet.</p>;
  }
  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead className="w-16">Order</TableHead>
          <TableHead>Batch</TableHead>
          <TableHead>Expiry</TableHead>
          <TableHead className="text-right">In stock</TableHead>
          <TableHead className="text-right">Cost</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {sorted.map((b, i) => (
          <TableRow key={b.id} className={cn(b.id === nextId && "bg-status-info-bg/50")}>
            <TableCell className="tabular-nums text-muted-foreground">{i + 1}</TableCell>
            <TableCell>
              <span className="font-medium tabular-nums">{b.batchNo}</span>
              {b.id === nextId ? (
                <Badge variant="outline" className={cn("ml-2 rounded-md", TONE_BOX.info)}>
                  <ClockIcon />
                  Sells first
                </Badge>
              ) : null}
            </TableCell>
            <TableCell>
              <div className="flex items-center gap-2">
                <span className="tabular-nums">{formatDate(b.expiryDate)}</span>
                <BatchChip expiryDate={b.expiryDate} today={today} />
              </div>
            </TableCell>
            <TableCell className="text-right tabular-nums">{b.stock}</TableCell>
            <TableCell className="text-right tabular-nums">{b.costPrice.toFixed(2)}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}
