"use client";

/**
 * Settings → Shelves (ST-05, plan B): shelves are rows of their own (`/shelves`), with a code unique in the pharmacy, a
 * description and the branch they're at. The design's `ShelvesList` to browse and export, `ManagedList` to change them.
 * Renaming a shelf moves its products with it; a shelf with products can't be deleted.
 */

import * as React from "react";

import { ShelvesList } from "@/components/medora/admin-more";
import { ManagedList, type ListItem } from "@/components/medora/managed-list";
import { Spinner } from "@/components/ui/spinner";
import { toast } from "@/components/ui/toast";
import { ShelvesApi, type ShelfRow } from "@/lib/api";
import { Loading } from "@/components/medora/loading";

const ALL = "All branches";
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 ShelvesSection({ readOnly, canExport, branches }: { readOnly: boolean; canExport: boolean; branches: { id: number; name: string }[] }) {
  const [rows, setRows] = React.useState<ShelfRow[] | null>(null);
  const [busy, setBusy] = React.useState(false);
  const load = React.useCallback(() => ShelvesApi.list().then(setRows).catch(() => setRows([])), []);
  React.useEffect(() => void load(), [load]);

  const branchId = (name?: string) => (!name || name === ALL ? null : (branches.find((b) => b.name === name)?.id ?? null));

  /** ManagedList hands back the whole list; turn the difference into API calls, then reload. */
  const apply = async (next: ListItem[]) => {
    const before = new Map((rows ?? []).map((r) => [String(r.id), r]));
    setBusy(true);
    try {
      for (const it of next) {
        const old = before.get(it.id);
        const body = { code: it.name, description: it.short ?? "", branchId: branchId(it.parent) };
        if (!old) await ShelvesApi.create(body);
        else if (old.code !== it.name.trim().toUpperCase() || old.description !== (it.short ?? "") || old.branch !== (it.parent ?? ALL) || old.active !== it.active) {
          await ShelvesApi.update(old.id, { ...body, active: it.active });
        }
      }
      for (const [id] of before) if (!next.some((it) => it.id === id)) await ShelvesApi.remove(Number(id));
    } catch (e) {
      toast.add({ type: "error", title: "Shelves not saved", description: apiError(e, "Try again.") });
    } finally {
      await load();
      setBusy(false);
    }
  };

  if (rows === null) {
    return (
      <Loading what="shelves" columns={3} rows={5} numeric={[1]} />
    );
  }
  return (
    <div className="space-y-4">
      <ShelvesList canExport={canExport} shelves={rows.map((r) => ({ code: r.code, description: [r.description, r.branch !== ALL ? r.branch : ""].filter(Boolean).join(" · "), products: r.products }))} />
      {readOnly ? null : (
        <div className="space-y-2">
          <p className="flex items-center gap-2 text-sm font-medium">Change shelves {busy ? <Spinner /> : null}</p>
          <ManagedList
            spec={{ noun: "shelf", usedBy: "products", short: { label: "Description", max: 120 }, parents: { label: "Branch", options: [ALL, ...branches.map((b) => b.name)] } }}
            items={rows.map((r) => ({ id: String(r.id), name: r.code, short: r.description, parent: r.branch, active: r.active, uses: r.products }))}
            onChange={(items) => void apply(items)}
            onNotice={(title, description) => toast.add({ title, description })}
          />
        </div>
      )}
    </div>
  );
}
