// Composants UI reutilisables — palette warm artisanal
// Inspires du dashboard atelier (memes polices, memes couleurs, meme tonalite)

// ============================================================
// Hooks utilitaires
// ============================================================

function useAsyncData(loader, deps = []) {
  const [data, setData] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const reload = React.useCallback(() => {
    setLoading(true);
    loader()
      .then((d) => { setData(d); setError(null); })
      .catch((e) => setError(e.message || String(e)))
      .finally(() => setLoading(false));
  }, deps);
  React.useEffect(() => { reload(); }, [reload]);
  return { data, error, loading, reload, setData };
}

// Toast "Sauvegarde" affiche brievement apres une PUT/POST
const ToastContext = React.createContext({ showToast: () => {} });

function ToastProvider({ children }) {
  const [toasts, setToasts] = React.useState([]);
  const showToast = (msg, kind = "ok") => {
    const id = Date.now() + Math.random();
    setToasts((prev) => [...prev, { id, msg, kind }]);
    setTimeout(() => setToasts((prev) => prev.filter((t) => t.id !== id)), 1700);
  };
  return (
    <ToastContext.Provider value={{ showToast }}>
      {children}
      <div className="fixed top-4 left-1/2 -translate-x-1/2 z-50 flex flex-col gap-2 pointer-events-none">
        {toasts.map((t) => (
          <div
            key={t.id}
            className={`toast-saved px-4 py-2 rounded-full text-sm shadow-md backdrop-blur ${
              t.kind === "ok"
                ? "bg-[oklch(0.62_0.14_145_/_0.95)] text-white"
                : "bg-[oklch(0.58_0.18_30_/_0.95)] text-white"
            }`}
          >
            {t.msg}
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

const useToast = () => React.useContext(ToastContext);

// ============================================================
// Sector badge (Pain / Viennoiserie)
// ============================================================

function SectorBadge({ secteur }) {
  const isPain = secteur === "pain";
  return (
    <span
      className={`inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium tracking-wide uppercase ${
        isPain
          ? "bg-[var(--pain-100)] text-[var(--pain-900)]"
          : "bg-[var(--vien-100)] text-[var(--vien-900)]"
      }`}
    >
      <span className={`w-1.5 h-1.5 rounded-full ${isPain ? "bg-[var(--pain-500)]" : "bg-[var(--vien-500)]"}`}></span>
      {isPain ? "Pain" : "Viennoiserie"}
    </span>
  );
}

// ============================================================
// Statut complet/incomplet
// ============================================================

function StatutBadge({ statut, size = "sm" }) {
  const ok = statut === "complet";
  const cls =
    size === "sm"
      ? "text-xs px-2 py-0.5"
      : "text-sm px-2.5 py-1";
  return (
    <span
      className={`inline-flex items-center gap-1.5 rounded-full font-medium ${cls} ${
        ok
          ? "bg-[oklch(0.94_0.05_145)] text-[oklch(0.32_0.10_145)]"
          : "bg-[oklch(0.94_0.05_75)] text-[oklch(0.42_0.10_55)]"
      }`}
    >
      <span className={`w-1.5 h-1.5 rounded-full ${ok ? "bg-[var(--ok)]" : "bg-[var(--warn)]"}`}></span>
      {ok ? "Complet" : "À compléter"}
    </span>
  );
}

// ============================================================
// Champ editable inline (texte / nombre)
// Auto-save sur blur — appelle onSave(newValue)
// ============================================================

function EditableField({ value, onSave, type = "text", placeholder = "—", className = "", numeric = false, inputMode }) {
  const [val, setVal] = React.useState(value ?? "");
  const [saving, setSaving] = React.useState(false);
  React.useEffect(() => { setVal(value ?? ""); }, [value]);

  const handleBlur = async () => {
    const current = val;
    const before = value ?? "";
    if (String(current) === String(before)) return;
    setSaving(true);
    try {
      let toSend = current === "" ? null : current;
      if (numeric && toSend !== null) {
        const n = Number(String(toSend).replace(",", "."));
        toSend = isNaN(n) ? null : n;
      }
      await onSave(toSend);
    } catch (e) {
      setVal(value ?? "");
    } finally {
      setSaving(false);
    }
  };

  return (
    <input
      type={type}
      inputMode={inputMode}
      value={val}
      placeholder={placeholder}
      onChange={(e) => setVal(e.target.value)}
      onBlur={handleBlur}
      disabled={saving}
      className={`field-edit ${numeric ? "font-mono tnum" : ""} ${className}`}
    />
  );
}

function EditableTextarea({ value, onSave, placeholder = "", className = "", rows = 8 }) {
  const [val, setVal] = React.useState(value ?? "");
  const [saving, setSaving] = React.useState(false);
  React.useEffect(() => { setVal(value ?? ""); }, [value]);

  const handleBlur = async () => {
    if ((val ?? "") === (value ?? "")) return;
    setSaving(true);
    try { await onSave(val === "" ? null : val); }
    catch (e) { setVal(value ?? ""); }
    finally { setSaving(false); }
  };

  return (
    <textarea
      value={val}
      placeholder={placeholder}
      onChange={(e) => setVal(e.target.value)}
      onBlur={handleBlur}
      disabled={saving}
      rows={rows}
      className={`field-edit w-full resize-y ${className}`}
    />
  );
}

// Cellule fourchette min-max
function RangeCell({ min, max, unite, onSaveMin, onSaveMax }) {
  return (
    <div className="inline-flex items-center gap-1">
      <EditableField
        value={min ?? ""}
        onSave={onSaveMin}
        numeric
        inputMode="decimal"
        placeholder="—"
        className="w-16 text-right"
      />
      <span className="text-[var(--ink-faint)] text-xs">→</span>
      <EditableField
        value={max ?? ""}
        onSave={onSaveMax}
        numeric
        inputMode="decimal"
        placeholder=""
        className="w-16 text-right"
      />
      <span className="text-[var(--ink-soft)] text-xs uppercase tracking-wide">{unite}</span>
    </div>
  );
}

// ============================================================
// Boutons & topbar
// ============================================================

function PrimaryButton({ children, onClick, type = "button", disabled = false, className = "" }) {
  return (
    <button
      type={type}
      onClick={onClick}
      disabled={disabled}
      className={`btn inline-flex items-center gap-1.5 px-3.5 py-2 rounded-full text-sm font-medium bg-[var(--pain-700)] text-white hover:bg-[var(--pain-900)] disabled:opacity-50 disabled:cursor-not-allowed ${className}`}
    >
      {children}
    </button>
  );
}

function SecondaryButton({ children, onClick, className = "" }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`btn inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-medium bg-white/70 hover:bg-white text-[var(--ink)] border border-[var(--line)] ${className}`}
    >
      {children}
    </button>
  );
}

function GhostButton({ children, onClick, className = "" }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`btn inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-[var(--ink-soft)] hover:bg-[var(--bg-soft)] hover:text-[var(--ink)] ${className}`}
    >
      {children}
    </button>
  );
}

function TopBar({ route, goRoute }) {
  const items = [
    { id: "recettes", label: "Recettes" },
    { id: "faconnages", label: "Façonnages" },
    { id: "incorporations", label: "Incorporations" },
    { id: "articles", label: "Articles" },
  ];
  return (
    <header className="sticky top-0 z-30 bg-[var(--bg)]/85 backdrop-blur border-b border-[var(--line-soft)]">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 py-3 flex items-center justify-between gap-4">
        <button
          onClick={() => goRoute({ name: "recettes" })}
          className="flex items-center gap-2 group"
        >
          <div className="w-8 h-8 rounded-full bg-[var(--pain-300)] grid place-items-center text-[var(--pain-900)] font-serif text-lg">é</div>
          <div className="leading-tight">
            <div className="font-serif text-lg">Recettes</div>
            <div className="text-[10px] uppercase tracking-widest text-[var(--ink-soft)] -mt-0.5">La Mie Dorée</div>
          </div>
        </button>
        <nav className="flex items-center gap-1 overflow-x-auto no-scrollbar -mx-2 px-2">
          {items.map((it) => {
            const active = route.name === it.id || (it.id === "recettes" && route.name === "recette");
            return (
              <button
                key={it.id}
                onClick={() => goRoute({ name: it.id })}
                className={`btn px-3 py-1.5 rounded-full text-sm whitespace-nowrap ${
                  active
                    ? "bg-[var(--ink)] text-white"
                    : "text-[var(--ink-soft)] hover:bg-[var(--bg-soft)]"
                }`}
              >
                {it.label}
              </button>
            );
          })}
        </nav>
      </div>
    </header>
  );
}

// ============================================================
// Page wrapper + states (loading / error / empty)
// ============================================================

function Page({ children, className = "" }) {
  return (
    <div className={`max-w-6xl mx-auto px-4 sm:px-6 py-6 sm:py-8 slide-up ${className}`}>
      {children}
    </div>
  );
}

function LoadingState() {
  return (
    <Page>
      <div className="text-center py-20 text-[var(--ink-faint)] font-serif text-2xl italic">
        Chargement…
      </div>
    </Page>
  );
}

function ErrorState({ error, onRetry }) {
  return (
    <Page>
      <div className="text-center py-20">
        <div className="font-serif text-3xl text-[var(--bad)] mb-2">Erreur</div>
        <div className="text-[var(--ink-soft)] mb-4">{error}</div>
        {onRetry && <SecondaryButton onClick={onRetry}>Réessayer</SecondaryButton>}
      </div>
    </Page>
  );
}

function EmptyState({ title, hint, action }) {
  return (
    <div className="text-center py-12">
      <div className="font-serif text-2xl italic text-[var(--ink-soft)] mb-2">{title}</div>
      {hint && <div className="text-sm text-[var(--ink-faint)] mb-4">{hint}</div>}
      {action}
    </div>
  );
}

// ============================================================
// Modal léger
// ============================================================

function Modal({ open, onClose, title, children, size = "md" }) {
  if (!open) return null;
  const widths = { sm: "max-w-sm", md: "max-w-lg", lg: "max-w-2xl" };
  return (
    <div className="fixed inset-0 z-40 fade-in">
      <div className="absolute inset-0 bg-[oklch(0.18_0.015_55_/_0.4)]" onClick={onClose}></div>
      <div className="relative h-full overflow-auto py-8 px-4 grid place-items-center">
        <div className={`w-full ${widths[size]} bg-[var(--bg-paper)] rounded-2xl shadow-xl border border-[var(--line)] slide-up`}>
          <div className="px-5 py-3 border-b border-[var(--line-soft)] flex items-center justify-between">
            <div className="font-serif text-xl">{title}</div>
            <button onClick={onClose} className="btn w-8 h-8 rounded-full hover:bg-[var(--bg-soft)] grid place-items-center text-[var(--ink-soft)]">×</button>
          </div>
          <div className="p-5">{children}</div>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// Confiance badge (pour mapping articles)
// ============================================================

function ConfianceBadge({ value, onClick }) {
  const map = {
    certain:   { label: "Certain",   bg: "oklch(0.94 0.05 145)", fg: "oklch(0.32 0.10 145)", dot: "var(--ok)" },
    hypothese: { label: "Hypothèse", bg: "oklch(0.94 0.05 75)",  fg: "oklch(0.42 0.10 55)",  dot: "var(--warn)" },
    inconnu:   { label: "Inconnu",   bg: "oklch(0.92 0.03 30)",  fg: "oklch(0.45 0.10 30)",  dot: "var(--bad)" },
  };
  const c = map[value] || { label: "—", bg: "oklch(0.92 0.014 70)", fg: "var(--ink-soft)", dot: "var(--ink-faint)" };
  return (
    <button
      type="button"
      onClick={onClick}
      className="btn inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium"
      style={{ background: c.bg, color: c.fg }}
    >
      <span className="w-1.5 h-1.5 rounded-full" style={{ background: c.dot }}></span>
      {c.label}
    </button>
  );
}

// Expose au global pour les autres scripts babel
window.UI = {
  useAsyncData, ToastProvider, useToast,
  SectorBadge, StatutBadge, ConfianceBadge,
  EditableField, EditableTextarea, RangeCell,
  PrimaryButton, SecondaryButton, GhostButton,
  TopBar, Page, LoadingState, ErrorState, EmptyState, Modal,
};
