"use client";

/**
 * Stock conversion (PRD 3.5, IN-21; plan A): link a product to its smaller unit and break parent units into it with the
 * design's `ConversionPreview`, and the Conversions tab with the design's `ConversionReport`. Converting can't be
 * undone (Q3); a mistake is corrected with a stock adjustment.
 */

import * as React from "react";

import { RecordDrawer } from "@/components/medora/drawer";
import { ConversionReport } from "@/components/medora/record-lists";
import { ConversionPreview } from "@/components/medora/stock-ops";
import { Button } from "@/components/ui/button";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { Spinner } from "@/components/ui/spinner";
import { toast } from "@/components/ui/toast";
import { StockOpsApi, type ConversionLinkRow, type ConversionRow, type OpsLocation } from "@/lib/api";
import { Loading } from "@/components/medora/loading";

const apiError = (e: unknown, fallback: string): string => {
  const m = (e as { response?: { data?: { message?: string | string[] } } })?.response?.data?.message;
  return Array.isArray(m) ? m.join(" ") : m || fallback;
};

export function ConversionsView() {
  const [rows, setRows] = React.useState<ConversionRow[] | null>(null);
  React.useEffect(() => {
    StockOpsApi.conversions()
      .then(setRows)
      .catch(() => setRows([]));
  }, []);
  if (rows === null) {
    return (
      <Loading what="conversions" columns={5} rows={5} numeric={[3, 4]} />
    );
  }
  if (!rows.length) return <p className="py-10 text-center text-sm text-muted-foreground">No conversions yet. Use Convert stock on a product that breaks into a smaller unit.</p>;
  return <ConversionReport rows={rows.map((r) => ({ no: r.no, date: r.date, parent: r.parent, child: r.child, parentQty: r.parentQty, childQty: r.childQty, location: r.location, staff: r.staff }))} />;
}

/** Converting one product: its link (set or change it), the location, and how many to break down. */
export function ConvertDrawer({ product, products, onClose, onDone }: { product: { id: number; name: string }; products: { id: number; name: string }[]; onClose: () => void; onDone: () => void }) {
  const [locations, setLocations] = React.useState<OpsLocation[] | null>(null);
  const [locationId, setLocationId] = React.useState<number | null>(null);
  const [link, setLink] = React.useState<ConversionLinkRow | null | undefined>(undefined);
  const [editing, setEditing] = React.useState(false);
  const [childId, setChildId] = React.useState("");
  const [per, setPer] = React.useState("");
  const [qty, setQty] = React.useState(0);
  const [busy, setBusy] = React.useState(false);

  React.useEffect(() => {
    StockOpsApi.locations()
      .then((l) => {
        setLocations(l);
        setLocationId((l.find((x) => x.own && x.isDefault) ?? l[0])?.id ?? null);
      })
      .catch(() => setLocations([]));
  }, []);

  const loadLink = React.useCallback(async () => {
    if (locationId == null) return;
    try {
      const r = await StockOpsApi.conversionOptions(locationId);
      const found = r.links.find((x) => x.productId === product.id) ?? null;
      setLink(found);
      setEditing(!found);
      setChildId(found ? String(found.childId) : "");
      setPer(found ? String(found.perParent) : "");
    } catch (e) {
      setLink(null);
      toast.add({ type: "error", title: "Couldn't load the conversion", description: apiError(e, "Try again.") });
    }
  }, [locationId, product.id]);
  React.useEffect(() => void loadLink(), [loadLink]);

  const saveLink = async () => {
    setBusy(true);
    try {
      await StockOpsApi.setLink(product.id, childId ? Number(childId) : null, Number(per));
      toast.add({ title: childId ? "Conversion saved" : "Conversion removed" });
      await loadLink();
    } catch (e) {
      toast.add({ type: "error", title: "Not saved", description: apiError(e, "Try again.") });
    } finally {
      setBusy(false);
    }
  };

  const convert = async () => {
    if (!link || !qty || locationId == null) return;
    setBusy(true);
    try {
      const r = await StockOpsApi.convert({ productId: product.id, quantity: qty, locationId });
      toast.add({ title: `${r.no}: converted`, description: `${r.parentQty} × ${r.parent} into ${r.childQty} × ${r.child}.` });
      onDone();
    } catch (e) {
      toast.add({ type: "error", title: "Not converted", description: apiError(e, "Try again.") });
      setBusy(false);
    }
  };

  return (
    <RecordDrawer
      open
      onOpenChange={(o) => !o && onClose()}
      variant="edit"
      width="lg"
      saving={busy}
      title={`Convert stock: ${product.name}`}
      subtitle="Break it into its smaller unit. This can't be undone."
      footer={
        <>
          <Button variant="outline" disabled={busy} onClick={onClose}>
            Close
          </Button>
          <Button disabled={busy || !link || editing || qty < 1} onClick={() => void convert()}>
            {busy ? <Spinner /> : null}
            Convert
          </Button>
        </>
      }
    >
      {locations === null || link === undefined ? (
        <Loading what="the conversion" shape="form" rows={4} />
      ) : (
        <div className="space-y-5">
          <Field>
            <FieldLabel htmlFor="c-loc">Location</FieldLabel>
            <NativeSelect id="c-loc" value={locationId ?? ""} onChange={(e) => { setLocationId(Number(e.target.value) || null); setQty(0); }}>
              {locations.map((l) => (
                <NativeSelectOption key={l.id} value={l.id}>
                  {l.branch}, {l.name}
                </NativeSelectOption>
              ))}
            </NativeSelect>
          </Field>

          {editing ? (
            <section aria-label="Conversion link" className="space-y-3 rounded-lg border border-[var(--color-border-panel)] p-3 bg-card">
              <div className="grid gap-3 sm:grid-cols-[1fr_8rem]">
                <Field>
                  <FieldLabel htmlFor="c-child">Breaks into</FieldLabel>
                  <NativeSelect id="c-child" value={childId} onChange={(e) => setChildId(e.target.value)}>
                    <NativeSelectOption value="">Choose the smaller unit</NativeSelectOption>
                    {products.filter((p) => p.id !== product.id).map((p) => (
                      <NativeSelectOption key={p.id} value={p.id}>
                        {p.name}
                      </NativeSelectOption>
                    ))}
                  </NativeSelect>
                </Field>
                <Field>
                  <FieldLabel htmlFor="c-per">How many in one</FieldLabel>
                  <Input id="c-per" inputMode="numeric" value={per} onChange={(e) => setPer(e.target.value.replace(/\D/g, ""))} placeholder="10" />
                </Field>
              </div>
              <FieldDescription>For example a box of 10 strips: choose the strip product and 10.</FieldDescription>
              <div className="flex gap-2">
                <Button size="sm" disabled={busy || !childId || !per} onClick={() => void saveLink()}>
                  Save conversion
                </Button>
                {link ? (
                  <Button size="sm" variant="ghost" onClick={() => setEditing(false)}>
                    Cancel
                  </Button>
                ) : null}
              </div>
            </section>
          ) : link ? (
            <>
              <ConversionPreview link={{ parent: { ...link.parent, unitCost: link.parent.unitCost ?? 0 }, child: link.child, perParent: link.perParent }} qty={qty} onQty={setQty} />
              <div className="flex flex-wrap gap-2">
                <Button size="sm" variant="outline" onClick={() => setEditing(true)}>
                  Change conversion
                </Button>
                <Button size="sm" variant="ghost" disabled={busy} onClick={() => { setChildId(""); void StockOpsApi.setLink(product.id, null).then(loadLink).catch((e) => toast.add({ type: "error", title: "Not removed", description: apiError(e, "Try again.") })); }}>
                  Remove conversion
                </Button>
              </div>
              <p className="text-xs text-muted-foreground">The earliest-expiring batches are converted first; each keeps its batch number and expiry. Cost per smaller unit is rounded to the cent.</p>
            </>
          ) : null}
        </div>
      )}
    </RecordDrawer>
  );
}
