// ============================================================
// Ecrans de l'application
// ============================================================

const {
  useAsyncData, useToast,
  SectorBadge, StatutBadge, ConfianceBadge,
  EditableField, EditableTextarea, RangeCell,
  PrimaryButton, SecondaryButton, GhostButton,
  Page, LoadingState, ErrorState, EmptyState, Modal,
} = window.UI;


// ============================================================
// Liste des recettes
// ============================================================

function ScreenListeRecettes({ goRoute }) {
  const { data, error, loading, reload } = useAsyncData(api.listRecettes, []);
  const [search, setSearch] = React.useState("");
  const [showNew, setShowNew] = React.useState(false);

  if (loading) return <LoadingState />;
  if (error)   return <ErrorState error={error} onRetry={reload} />;

  const filtered = (data || []).filter((r) =>
    !search || r.nom.toLowerCase().includes(search.toLowerCase())
  );

  // Trier : incomplets d'abord, puis ordre alpha
  filtered.sort((a, b) => {
    if (a.statut !== b.statut) return a.statut === "incomplet" ? -1 : 1;
    return a.nom.localeCompare(b.nom);
  });

  const groupes = {
    pain: filtered.filter((r) => r.secteur === "pain"),
    viennoiserie: filtered.filter((r) => r.secteur === "viennoiserie"),
  };

  return (
    <Page>
      <div className="flex items-end justify-between gap-4 mb-6">
        <div>
          <h1 className="font-serif text-4xl sm:text-5xl">Recettes</h1>
          <p className="text-[var(--ink-soft)] text-sm mt-1">
            Référentiel des pâtes mères et dérivées de la boulangerie.
          </p>
        </div>
        <PrimaryButton onClick={() => setShowNew(true)}>
          <span className="text-base leading-none">+</span> Nouvelle recette
        </PrimaryButton>
      </div>

      <div className="mb-6">
        <input
          type="search"
          placeholder="Rechercher une recette…"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="w-full px-4 py-2.5 rounded-full border border-[var(--line)] bg-white/60 focus:bg-white focus:outline-none focus:border-[var(--pain-300)]"
        />
      </div>

      {["pain", "viennoiserie"].map((sec) => {
        const list = groupes[sec];
        if (!list.length) return null;
        return (
          <section key={sec} className={`mb-10 sector-${sec === "pain" ? "pain" : "vien"}`}>
            <div className="flex items-baseline justify-between mb-3">
              <h2 className="font-serif text-2xl text-[var(--sec-700)]">
                {sec === "pain" ? "Pain" : "Viennoiserie"}
              </h2>
              <span className="text-xs uppercase tracking-widest text-[var(--ink-faint)]">
                {list.length} recette{list.length > 1 ? "s" : ""}
              </span>
            </div>
            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
              {list.map((r) => <RecetteCard key={r.id} recette={r} onClick={() => goRoute({ name: "recette", id: r.id })} />)}
            </div>
          </section>
        );
      })}

      {!filtered.length && (
        <EmptyState title="Aucune recette" hint="Crée une recette pour commencer." action={
          <PrimaryButton onClick={() => setShowNew(true)}>+ Nouvelle recette</PrimaryButton>
        } />
      )}

      {showNew && (
        <NewRecetteModal
          onClose={() => setShowNew(false)}
          onCreated={(r) => { setShowNew(false); goRoute({ name: "recette", id: r.id }); }}
        />
      )}
    </Page>
  );
}

function RecetteCard({ recette, onClick }) {
  const isPain = recette.secteur === "pain";
  return (
    <button
      onClick={onClick}
      className={`btn text-left rounded-2xl p-4 border transition-all hover:shadow-md ${
        isPain
          ? "bg-[var(--pain-50)] border-[var(--pain-100)] hover:border-[var(--pain-300)]"
          : "bg-[var(--vien-50)] border-[var(--vien-100)] hover:border-[var(--vien-300)]"
      }`}
    >
      <div className="flex items-start justify-between mb-2">
        <h3 className="font-serif text-2xl leading-tight">{recette.nom}</h3>
        <StatutBadge statut={recette.statut} />
      </div>
      {recette.type_recette === "derivee" && recette.recette_parente_id && (
        <div className="text-xs text-[var(--ink-faint)] mb-2 italic">
          dérivée de <span className="not-italic">{recette.recette_parente_id}</span>
        </div>
      )}
      <div className="flex items-center gap-3 text-xs text-[var(--ink-soft)] mt-3 font-mono tnum">
        <span>{recette.nb_baremes} bac{recette.nb_baremes !== 1 ? "s" : ""}</span>
        <span className="text-[var(--ink-faint)]">·</span>
        <span>{recette.cycle_production_jours ? `${recette.cycle_production_jours} j cycle` : "cycle ?"}</span>
        <span className="text-[var(--ink-faint)]">·</span>
        <span>{recette.nb_articles} article{recette.nb_articles !== 1 ? "s" : ""}</span>
      </div>
    </button>
  );
}

function NewRecetteModal({ onClose, onCreated }) {
  const [nom, setNom] = React.useState("");
  const [secteur, setSecteur] = React.useState("pain");
  const [type, setType] = React.useState("mere");
  const [parenteId, setParenteId] = React.useState("");
  const [parents, setParents] = React.useState([]);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const { showToast } = useToast();

  React.useEffect(() => {
    api.listRecettes().then((rs) => setParents(rs.filter((r) => r.type_recette === "mere"))).catch(() => {});
  }, []);

  const submit = async () => {
    if (!nom.trim()) return setErr("Nom requis");
    setBusy(true); setErr(null);
    try {
      const r = await api.createRecette({
        nom: nom.trim(),
        secteur,
        type_recette: type,
        recette_parente_id: type === "derivee" ? (parenteId || null) : null,
      });
      showToast("Recette créée");
      onCreated(r);
    } catch (e) {
      setErr(e.message);
    } finally { setBusy(false); }
  };

  return (
    <Modal open onClose={onClose} title="Nouvelle recette">
      <div className="space-y-3">
        <div>
          <label className="text-xs uppercase tracking-widest text-[var(--ink-soft)]">Nom</label>
          <input autoFocus value={nom} onChange={(e) => setNom(e.target.value)}
            className="w-full mt-1 px-3 py-2 rounded-lg border border-[var(--line)] bg-white" />
        </div>
        <div className="grid grid-cols-2 gap-3">
          <div>
            <label className="text-xs uppercase tracking-widest text-[var(--ink-soft)]">Secteur</label>
            <select value={secteur} onChange={(e) => setSecteur(e.target.value)}
              className="w-full mt-1 px-3 py-2 rounded-lg border border-[var(--line)] bg-white">
              <option value="pain">Pain</option>
              <option value="viennoiserie">Viennoiserie</option>
            </select>
          </div>
          <div>
            <label className="text-xs uppercase tracking-widest text-[var(--ink-soft)]">Type</label>
            <select value={type} onChange={(e) => setType(e.target.value)}
              className="w-full mt-1 px-3 py-2 rounded-lg border border-[var(--line)] bg-white">
              <option value="mere">Mère</option>
              <option value="derivee">Dérivée</option>
            </select>
          </div>
        </div>
        {type === "derivee" && (
          <div>
            <label className="text-xs uppercase tracking-widest text-[var(--ink-soft)]">Recette parente</label>
            <select value={parenteId} onChange={(e) => setParenteId(e.target.value)}
              className="w-full mt-1 px-3 py-2 rounded-lg border border-[var(--line)] bg-white">
              <option value="">— aucune —</option>
              {parents.map((p) => <option key={p.id} value={p.id}>{p.nom}</option>)}
            </select>
          </div>
        )}
        {err && <div className="text-sm text-[var(--bad)]">{err}</div>}
        <div className="flex justify-end gap-2 pt-2">
          <SecondaryButton onClick={onClose}>Annuler</SecondaryButton>
          <PrimaryButton onClick={submit} disabled={busy}>Créer</PrimaryButton>
        </div>
      </div>
    </Modal>
  );
}


// ============================================================
// Edition d'une recette
// ============================================================

function ScreenEditRecette({ recetteId, goRoute }) {
  const { data, error, loading, reload, setData } = useAsyncData(() => api.getRecette(recetteId), [recetteId]);
  const [petrins, setPetrins] = React.useState([]);
  const { showToast } = useToast();

  React.useEffect(() => { api.listPetrins().then(setPetrins).catch(() => {}); }, []);

  if (loading) return <LoadingState />;
  if (error)   return <ErrorState error={error} onRetry={reload} />;
  if (!data)   return null;

  const isPain = data.secteur === "pain";
  const sectorClass = isPain ? "sector-pain" : "sector-vien";

  const updateRecette = async (patch) => {
    try {
      const updated = await api.updateRecette(recetteId, patch);
      setData(updated);
      showToast("Sauvegardé");
    } catch (e) { showToast(e.message, "err"); throw e; }
  };

  const deleteRecette = async () => {
    if (!confirm(`Supprimer la recette "${data.nom}" ? Les barèmes et ingrédients seront perdus.`)) return;
    try {
      await api.deleteRecette(recetteId);
      showToast("Recette supprimée");
      goRoute({ name: "recettes" });
    } catch (e) { showToast(e.message, "err"); }
  };

  return (
    <Page className={sectorClass}>
      {/* Fil d'Ariane */}
      <div className="text-sm text-[var(--ink-soft)] mb-4 flex items-center gap-2">
        <button onClick={() => goRoute({ name: "recettes" })} className="hover:text-[var(--ink)] underline-offset-2 hover:underline">
          Recettes
        </button>
        <span className="text-[var(--ink-faint)]">/</span>
        <span className="text-[var(--ink)]">{data.nom}</span>
      </div>

      {/* En-tete */}
      <div className="mb-8">
        <div className="flex items-start justify-between gap-4 mb-3">
          <div className="flex-1">
            <EditableField
              value={data.nom}
              onSave={(v) => updateRecette({ nom: v })}
              className="font-serif text-4xl sm:text-5xl w-full"
            />
            {data.type_recette === "derivee" && data.recette_parente_id && (
              <div className="text-sm text-[var(--ink-soft)] italic mt-1">
                dérivée de{" "}
                <button
                  onClick={() => goRoute({ name: "recette", id: data.recette_parente_id })}
                  className="not-italic underline-offset-2 hover:underline text-[var(--ink)]"
                >
                  {data.recette_parente_id}
                </button>
              </div>
            )}
          </div>
          <div className="flex items-center gap-2 flex-shrink-0">
            <SectorBadge secteur={data.secteur} />
            <StatutBadge statut={data.statut} size="md" />
          </div>
        </div>

        <div className="grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm">
          <Field label="Cycle de production">
            <div className="flex items-baseline gap-1">
              <EditableField
                value={data.cycle_production_jours ?? ""}
                onSave={(v) => updateRecette({ cycle_production_jours: v })}
                numeric inputMode="numeric" placeholder="—" className="w-12 text-right"
              />
              <span className="text-[var(--ink-soft)]">jours</span>
            </div>
            <EditableField
              value={data.cycle_production_notes ?? ""}
              onSave={(v) => updateRecette({ cycle_production_notes: v })}
              placeholder="ex : généralement 2, parfois 3"
              className="text-xs italic text-[var(--ink-soft)] w-full mt-1"
            />
          </Field>
          <Field label="Méthode de blocage">
            <EditableField
              value={data.methode_blocage ?? ""}
              onSave={(v) => updateRecette({ methode_blocage: v })}
              placeholder="façonnage congelé, pâte en bac, aucun…"
              className="w-full"
            />
          </Field>
          <Field label="Type">
            <span className="text-[var(--ink)] capitalize">{data.type_recette}</span>
          </Field>
        </div>
      </div>

      {/* Baremes */}
      <Section title="Barèmes">
        <BaremeTable
          recetteId={recetteId}
          baremes={data.baremes}
          petrins={petrins}
          onChange={reload}
        />
      </Section>

      {/* Notes process — savoir-faire libre */}
      <Section title="Notes de process" subtitle="le savoir-faire libre">
        <div className="bg-[var(--bg-paper)] border border-[var(--line)] rounded-xl p-4 sm:p-6 paper">
          <EditableTextarea
            value={data.notes_process ?? ""}
            onSave={(v) => updateRecette({ notes_process: v })}
            placeholder="Bassinage, frasage, vitesses, rabats, trempage céréales, températures, repères du métier…"
            rows={8}
            className="font-serif italic text-base text-[var(--ink)] bg-transparent"
          />
        </div>
      </Section>

      {/* Articles produits */}
      {data.articles && data.articles.length > 0 && (
        <Section title="Articles produits" subtitle={`${data.articles.length} référence${data.articles.length > 1 ? "s" : ""}`}>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
            {data.articles.map((a) => (
              <button
                key={a.code}
                onClick={() => goRoute({ name: "articles" })}
                className="btn text-left flex items-center justify-between gap-3 p-3 rounded-lg bg-white/60 hover:bg-white border border-[var(--line-soft)]"
              >
                <div className="min-w-0">
                  <div className="text-sm truncate">{a.designation}</div>
                  <div className="text-[10px] uppercase tracking-widest text-[var(--ink-faint)] font-mono">{a.code}</div>
                </div>
                <div className="text-xs text-[var(--ink-soft)] flex flex-col items-end gap-0.5">
                  {a.faconnage_nom && <span>{a.faconnage_nom}</span>}
                  {a.incorporation_nom && <span className="italic">+ {a.incorporation_nom}</span>}
                </div>
              </button>
            ))}
          </div>
        </Section>
      )}

      {/* Recettes derivees */}
      {data.recettes_derivees && data.recettes_derivees.length > 0 && (
        <Section title="Recettes dérivées">
          <div className="flex flex-wrap gap-2">
            {data.recettes_derivees.map((id) => (
              <button
                key={id}
                onClick={() => goRoute({ name: "recette", id })}
                className="btn px-3 py-1.5 rounded-full bg-white/60 hover:bg-white border border-[var(--line)] text-sm"
              >
                {id}
              </button>
            ))}
          </div>
        </Section>
      )}

      {/* Footer actions */}
      <div className="mt-12 pt-6 border-t border-[var(--line-soft)] flex items-center justify-between">
        <div className="text-xs text-[var(--ink-faint)] font-mono">
          Modifié le {new Date(data.modifie_le).toLocaleString("fr-FR")}
        </div>
        <button
          onClick={deleteRecette}
          className="btn text-sm text-[var(--bad)] hover:underline-offset-2 hover:underline"
        >
          Supprimer la recette
        </button>
      </div>
    </Page>
  );
}

function Field({ label, children }) {
  return (
    <div>
      <div className="text-xs uppercase tracking-widest text-[var(--ink-faint)] mb-1">{label}</div>
      <div>{children}</div>
    </div>
  );
}

function Section({ title, subtitle, children }) {
  return (
    <section className="mb-8">
      <div className="flex items-baseline gap-3 mb-3">
        <h2 className="font-serif text-2xl text-[var(--ink)]">{title}</h2>
        {subtitle && <span className="text-xs uppercase tracking-widest text-[var(--ink-faint)]">{subtitle}</span>}
      </div>
      {children}
    </section>
  );
}


// ============================================================
// Tableau editable barèmes + ingredients
// ============================================================

function BaremeTable({ recetteId, baremes, petrins, onChange }) {
  const { showToast } = useToast();

  // Toutes les colonnes ingredient distinctes (par nom)
  const ingredientNames = React.useMemo(() => {
    const set = new Set();
    baremes.forEach((b) => b.ingredients.forEach((i) => set.add(i.nom)));
    return Array.from(set);
  }, [baremes]);

  const addBareme = async () => {
    const lastBac = baremes.length ? Math.max(...baremes.map((b) => b.bac_num)) : 0;
    const farine = prompt("Taille du bac (kg de farine) :", "5");
    if (!farine) return;
    try {
      await api.createBareme(recetteId, {
        bac_num: lastBac + 1,
        farine_kg: Number(farine.replace(",", ".")),
        ingredients: ingredientNames.map((nom, idx) => ({ nom, unite: nom.toLowerCase().includes("eau") ? "L" : "g", ordre: idx })),
      });
      showToast("Bac ajouté");
      onChange();
    } catch (e) { showToast(e.message, "err"); }
  };

  const deleteBareme = async (bareme) => {
    if (!confirm(`Supprimer le bac ${bareme.bac_num} ?`)) return;
    try {
      await api.deleteBareme(bareme.id);
      showToast("Bac supprimé");
      onChange();
    } catch (e) { showToast(e.message, "err"); }
  };

  const addIngredient = async () => {
    const nom = prompt("Nom de l'ingrédient :", "");
    if (!nom || !nom.trim()) return;
    const unite = prompt("Unité (g, kg, L) :", "g") || "g";
    try {
      // ajouter sur tous les baremes
      for (const b of baremes) {
        await api.createIngredient(b.id, {
          nom: nom.trim(),
          unite,
          ordre: b.ingredients.length,
        });
      }
      showToast("Ingrédient ajouté");
      onChange();
    } catch (e) { showToast(e.message, "err"); }
  };

  const updateIngredient = async (ing, patch) => {
    try { await api.updateIngredient(ing.id, patch); showToast("Sauvegardé"); onChange(); }
    catch (e) { showToast(e.message, "err"); throw e; }
  };

  const updateBareme = async (bareme, patch) => {
    try { await api.updateBareme(bareme.id, patch); showToast("Sauvegardé"); onChange(); }
    catch (e) { showToast(e.message, "err"); throw e; }
  };

  if (!baremes.length) {
    return (
      <div className="border border-dashed border-[var(--line)] rounded-xl p-6 text-center bg-white/40">
        <div className="font-serif text-lg italic text-[var(--ink-soft)] mb-3">Aucun barème encore.</div>
        <PrimaryButton onClick={addBareme}>+ Ajouter un premier bac</PrimaryButton>
      </div>
    );
  }

  return (
    <div className="overflow-x-auto -mx-4 sm:mx-0 px-4 sm:px-0">
      <table className="w-full border-collapse">
        <thead>
          <tr className="text-left text-xs uppercase tracking-widest text-[var(--ink-faint)] border-b border-[var(--line)]">
            <th className="px-3 py-2 sticky left-0 bg-[var(--bg)] z-10">Bac</th>
            <th className="px-3 py-2">Farine</th>
            <th className="px-3 py-2">Pétrin</th>
            {ingredientNames.map((nom) => (
              <th key={nom} className="px-3 py-2 whitespace-nowrap">{nom}</th>
            ))}
            <th className="px-3 py-2 w-8"></th>
          </tr>
        </thead>
        <tbody>
          {baremes.map((b) => (
            <tr key={b.id} className="border-b border-[var(--line-soft)] hover:bg-[var(--bg-paper)]/60">
              <td className="px-3 py-2 sticky left-0 bg-[var(--bg)] z-10 font-mono tnum text-sm">
                Bac {b.bac_num}
              </td>
              <td className="px-3 py-2">
                <div className="flex items-baseline gap-1">
                  <EditableField
                    value={b.farine_kg}
                    onSave={(v) => updateBareme(b, { farine_kg: v })}
                    numeric inputMode="decimal" className="w-16 text-right"
                  />
                  <span className="text-xs uppercase text-[var(--ink-soft)]">kg</span>
                </div>
              </td>
              <td className="px-3 py-2">
                <select
                  value={b.petrin_id ?? ""}
                  onChange={(e) => updateBareme(b, { petrin_id: e.target.value === "" ? null : Number(e.target.value) })}
                  className="field-edit text-sm"
                >
                  <option value="">—</option>
                  {petrins.map((p) => <option key={p.id} value={p.id}>{p.nom}</option>)}
                </select>
              </td>
              {ingredientNames.map((nom) => {
                const ing = b.ingredients.find((i) => i.nom === nom);
                if (!ing) {
                  return (
                    <td key={nom} className="px-3 py-2">
                      <button
                        onClick={async () => {
                          try {
                            await api.createIngredient(b.id, {
                              nom,
                              unite: nom.toLowerCase().includes("eau") ? "L" : "g",
                              ordre: b.ingredients.length,
                            });
                            onChange();
                          } catch (e) { showToast(e.message, "err"); }
                        }}
                        className="btn text-xs text-[var(--ink-faint)] hover:text-[var(--ink)] italic"
                      >
                        + ajouter
                      </button>
                    </td>
                  );
                }
                return (
                  <td key={nom} className="px-3 py-2 whitespace-nowrap">
                    <RangeCell
                      min={ing.quantite_min}
                      max={ing.quantite_max}
                      unite={ing.unite}
                      onSaveMin={(v) => updateIngredient(ing, { quantite_min: v, quantite_max: ing.quantite_max ?? v })}
                      onSaveMax={(v) => updateIngredient(ing, { quantite_max: v })}
                    />
                  </td>
                );
              })}
              <td className="px-3 py-2">
                <GhostButton onClick={() => deleteBareme(b)}>×</GhostButton>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <div className="flex gap-2 mt-3">
        <SecondaryButton onClick={addBareme}>+ Bac</SecondaryButton>
        <SecondaryButton onClick={addIngredient}>+ Ingrédient</SecondaryButton>
      </div>
    </div>
  );
}


// ============================================================
// Faconnages
// ============================================================

function ScreenFaconnages() {
  const { data, error, loading, reload, setData } = useAsyncData(api.listFaconnages, []);
  const { showToast } = useToast();

  if (loading) return <LoadingState />;
  if (error)   return <ErrorState error={error} onRetry={reload} />;

  const update = async (id, patch) => {
    try { const r = await api.updateFaconnage(id, patch); setData((d) => d.map((x) => x.id === id ? r : x)); showToast("Sauvegardé"); }
    catch (e) { showToast(e.message, "err"); throw e; }
  };
  const create = async () => {
    const nom = prompt("Nom du façonnage :", "");
    if (!nom) return;
    try { await api.createFaconnage({ nom: nom.trim() }); reload(); showToast("Créé"); }
    catch (e) { showToast(e.message, "err"); }
  };
  const remove = async (id) => {
    if (!confirm("Supprimer ce façonnage ?")) return;
    try { await api.deleteFaconnage(id); reload(); showToast("Supprimé"); }
    catch (e) { showToast(e.message, "err"); }
  };

  return (
    <Page>
      <div className="flex items-end justify-between gap-4 mb-6">
        <div>
          <h1 className="font-serif text-4xl sm:text-5xl">Façonnages</h1>
          <p className="text-[var(--ink-soft)] text-sm mt-1">
            Forme finale donnée à un pâton — poids unitaire et équivalence baguettes.
          </p>
        </div>
        <PrimaryButton onClick={create}>+ Nouveau</PrimaryButton>
      </div>
      <div className="overflow-x-auto -mx-4 sm:mx-0 px-4 sm:px-0">
        <table className="w-full border-collapse">
          <thead>
            <tr className="text-left text-xs uppercase tracking-widest text-[var(--ink-faint)] border-b border-[var(--line)]">
              <th className="px-3 py-2">Nom</th>
              <th className="px-3 py-2">Poids pâton (g)</th>
              <th className="px-3 py-2">Équivalence baguettes</th>
              <th className="px-3 py-2">Notes</th>
              <th className="px-3 py-2 w-8"></th>
            </tr>
          </thead>
          <tbody>
            {data.map((f) => (
              <tr key={f.id} className="border-b border-[var(--line-soft)] hover:bg-[var(--bg-paper)]/60">
                <td className="px-3 py-2">
                  <EditableField value={f.nom} onSave={(v) => update(f.id, { nom: v })} className="font-serif text-lg" />
                  <div className="text-[10px] font-mono uppercase text-[var(--ink-faint)] tracking-wider">{f.id}</div>
                </td>
                <td className="px-3 py-2">
                  <EditableField value={f.poids_paton_g ?? ""} onSave={(v) => update(f.id, { poids_paton_g: v })}
                    numeric inputMode="numeric" placeholder="—" className="w-20 text-right" />
                </td>
                <td className="px-3 py-2">
                  <EditableField value={f.equivalence_baguettes ?? ""} onSave={(v) => update(f.id, { equivalence_baguettes: v })}
                    numeric inputMode="decimal" placeholder="—" className="w-20 text-right" />
                </td>
                <td className="px-3 py-2">
                  <EditableField value={f.notes ?? ""} onSave={(v) => update(f.id, { notes: v })}
                    placeholder="…" className="w-full" />
                </td>
                <td className="px-3 py-2"><GhostButton onClick={() => remove(f.id)}>×</GhostButton></td>
              </tr>
            ))}
            {!data.length && (
              <tr><td colSpan={5} className="text-center py-12">
                <EmptyState title="Aucun façonnage" />
              </td></tr>
            )}
          </tbody>
        </table>
      </div>
    </Page>
  );
}


// ============================================================
// Incorporations
// ============================================================

function ScreenIncorporations() {
  const { data, error, loading, reload, setData } = useAsyncData(api.listIncorporations, []);
  const { showToast } = useToast();

  if (loading) return <LoadingState />;
  if (error)   return <ErrorState error={error} onRetry={reload} />;

  const update = async (id, patch) => {
    try { const r = await api.updateIncorporation(id, patch); setData((d) => d.map((x) => x.id === id ? r : x)); showToast("Sauvegardé"); }
    catch (e) { showToast(e.message, "err"); throw e; }
  };
  const create = async () => {
    const nom = prompt("Nom de l'incorporation :", "");
    if (!nom) return;
    try { await api.createIncorporation({ nom: nom.trim() }); reload(); showToast("Créé"); }
    catch (e) { showToast(e.message, "err"); }
  };
  const remove = async (id) => {
    if (!confirm("Supprimer cette incorporation ?")) return;
    try { await api.deleteIncorporation(id); reload(); showToast("Supprimé"); }
    catch (e) { showToast(e.message, "err"); }
  };

  return (
    <Page>
      <div className="flex items-end justify-between gap-4 mb-6">
        <div>
          <h1 className="font-serif text-4xl sm:text-5xl">Incorporations</h1>
          <p className="text-[var(--ink-soft)] text-sm mt-1">
            Ajouts en cours de pétrissage — graines, fruits secs, levains spécifiques.
          </p>
        </div>
        <PrimaryButton onClick={create}>+ Nouvelle</PrimaryButton>
      </div>
      <div className="overflow-x-auto -mx-4 sm:mx-0 px-4 sm:px-0">
        <table className="w-full border-collapse">
          <thead>
            <tr className="text-left text-xs uppercase tracking-widest text-[var(--ink-faint)] border-b border-[var(--line)]">
              <th className="px-3 py-2">Nom</th>
              <th className="px-3 py-2">Dosage (g)</th>
              <th className="px-3 py-2">Bac réf. (kg farine)</th>
              <th className="px-3 py-2">Méthode</th>
              <th className="px-3 py-2 w-8"></th>
            </tr>
          </thead>
          <tbody>
            {data.map((i) => (
              <tr key={i.id} className="border-b border-[var(--line-soft)] hover:bg-[var(--bg-paper)]/60">
                <td className="px-3 py-2">
                  <EditableField value={i.nom} onSave={(v) => update(i.id, { nom: v })} className="font-serif text-lg" />
                  <div className="text-[10px] font-mono uppercase text-[var(--ink-faint)] tracking-wider">{i.id}</div>
                </td>
                <td className="px-3 py-2">
                  <EditableField value={i.dosage_par_bac_g ?? ""} onSave={(v) => update(i.id, { dosage_par_bac_g: v })}
                    numeric inputMode="decimal" placeholder="—" className="w-24 text-right" />
                </td>
                <td className="px-3 py-2">
                  <EditableField value={i.bac_reference_kg ?? ""} onSave={(v) => update(i.id, { bac_reference_kg: v })}
                    numeric inputMode="decimal" placeholder="—" className="w-20 text-right" />
                </td>
                <td className="px-3 py-2 max-w-md">
                  <EditableField value={i.methode_application ?? ""} onSave={(v) => update(i.id, { methode_application: v })}
                    placeholder="…" className="w-full" />
                </td>
                <td className="px-3 py-2"><GhostButton onClick={() => remove(i.id)}>×</GhostButton></td>
              </tr>
            ))}
            {!data.length && (
              <tr><td colSpan={5} className="text-center py-12">
                <EmptyState title="Aucune incorporation" />
              </td></tr>
            )}
          </tbody>
        </table>
      </div>
    </Page>
  );
}


// ============================================================
// Mapping articles
// ============================================================

function ScreenArticles() {
  const { data, error, loading, reload, setData } = useAsyncData(api.listArticles, []);
  const [recettes, setRecettes] = React.useState([]);
  const [faconnages, setFaconnages] = React.useState([]);
  const [incorporations, setIncorporations] = React.useState([]);
  const [filterFamille, setFilterFamille] = React.useState("");
  const [filterRecette, setFilterRecette] = React.useState("");
  const [filterConfiance, setFilterConfiance] = React.useState("");
  const [search, setSearch] = React.useState("");
  const { showToast } = useToast();

  React.useEffect(() => {
    api.listRecettes().then(setRecettes).catch(() => {});
    api.listFaconnages().then(setFaconnages).catch(() => {});
    api.listIncorporations().then(setIncorporations).catch(() => {});
  }, []);

  if (loading) return <LoadingState />;
  if (error)   return <ErrorState error={error} onRetry={reload} />;

  const updateMapping = async (code, patch) => {
    try {
      const updated = await api.updateMapping(code, patch);
      setData((d) => d.map((a) => a.code === code ? updated : a));
      showToast("Sauvegardé");
    } catch (e) { showToast(e.message, "err"); throw e; }
  };

  const familles = Array.from(new Set(data.map((a) => a.famille))).sort();
  const filtered = data.filter((a) =>
    (!filterFamille || a.famille === filterFamille) &&
    (!filterRecette || a.recette_id === filterRecette) &&
    (!filterConfiance || a.confiance === filterConfiance) &&
    (!search || a.designation.toLowerCase().includes(search.toLowerCase()) || a.code.includes(search))
  );

  return (
    <Page>
      <div className="mb-6">
        <h1 className="font-serif text-4xl sm:text-5xl">Articles</h1>
        <p className="text-[var(--ink-soft)] text-sm mt-1">
          Mapping des {data.length} articles Kwisatz vers leur recette mère et leur façonnage.
        </p>
      </div>

      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2 mb-4">
        <input
          type="search" value={search} onChange={(e) => setSearch(e.target.value)}
          placeholder="Rechercher article ou code…"
          className="px-3 py-2 rounded-full border border-[var(--line)] bg-white/60 focus:bg-white focus:outline-none text-sm"
        />
        <select value={filterFamille} onChange={(e) => setFilterFamille(e.target.value)}
          className="px-3 py-2 rounded-full border border-[var(--line)] bg-white/60 text-sm">
          <option value="">Toutes familles</option>
          {familles.map((f) => <option key={f} value={f}>{f}</option>)}
        </select>
        <select value={filterRecette} onChange={(e) => setFilterRecette(e.target.value)}
          className="px-3 py-2 rounded-full border border-[var(--line)] bg-white/60 text-sm">
          <option value="">Toutes recettes</option>
          {recettes.map((r) => <option key={r.id} value={r.id}>{r.nom}</option>)}
        </select>
        <select value={filterConfiance} onChange={(e) => setFilterConfiance(e.target.value)}
          className="px-3 py-2 rounded-full border border-[var(--line)] bg-white/60 text-sm">
          <option value="">Toute confiance</option>
          <option value="certain">Certain</option>
          <option value="hypothese">Hypothèse</option>
          <option value="inconnu">Inconnu</option>
        </select>
      </div>

      <div className="overflow-x-auto -mx-4 sm:mx-0 px-4 sm:px-0 text-sm">
        <table className="w-full border-collapse">
          <thead>
            <tr className="text-left text-xs uppercase tracking-widest text-[var(--ink-faint)] border-b border-[var(--line)]">
              <th className="px-2 py-2">Code</th>
              <th className="px-2 py-2">Désignation</th>
              <th className="px-2 py-2">Famille</th>
              <th className="px-2 py-2">Recette</th>
              <th className="px-2 py-2">Façonnage</th>
              <th className="px-2 py-2">Incorporation</th>
              <th className="px-2 py-2">Variante</th>
              <th className="px-2 py-2">Confiance</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((a) => (
              <tr key={a.code} className="border-b border-[var(--line-soft)] hover:bg-[var(--bg-paper)]/60">
                <td className="px-2 py-2 font-mono tnum text-xs">{a.code}</td>
                <td className="px-2 py-2">{a.designation}</td>
                <td className="px-2 py-2">
                  <span className="text-xs uppercase tracking-widest text-[var(--ink-faint)]">{a.famille}</span>
                </td>
                <td className="px-2 py-2">
                  <select
                    value={a.recette_id ?? ""}
                    onChange={(e) => updateMapping(a.code, { recette_id: e.target.value || null })}
                    className="field-edit text-sm w-40"
                  >
                    <option value="">—</option>
                    {recettes.map((r) => <option key={r.id} value={r.id}>{r.nom}</option>)}
                  </select>
                </td>
                <td className="px-2 py-2">
                  <select
                    value={a.faconnage_id ?? ""}
                    onChange={(e) => updateMapping(a.code, { faconnage_id: e.target.value || null })}
                    className="field-edit text-sm w-32"
                  >
                    <option value="">—</option>
                    {faconnages.map((f) => <option key={f.id} value={f.id}>{f.nom}</option>)}
                  </select>
                </td>
                <td className="px-2 py-2">
                  <select
                    value={a.incorporation_id ?? ""}
                    onChange={(e) => updateMapping(a.code, { incorporation_id: e.target.value || null })}
                    className="field-edit text-sm w-36"
                  >
                    <option value="">—</option>
                    {incorporations.map((i) => <option key={i.id} value={i.id}>{i.nom}</option>)}
                  </select>
                </td>
                <td className="px-2 py-2">
                  <EditableField
                    value={a.variante ?? ""}
                    onSave={(v) => updateMapping(a.code, { variante: v })}
                    placeholder="—"
                    className="w-24"
                  />
                </td>
                <td className="px-2 py-2">
                  <select
                    value={a.confiance ?? ""}
                    onChange={(e) => updateMapping(a.code, { confiance: e.target.value || null })}
                    className="field-edit text-sm"
                  >
                    <option value="">—</option>
                    <option value="certain">Certain</option>
                    <option value="hypothese">Hypothèse</option>
                    <option value="inconnu">Inconnu</option>
                  </select>
                </td>
              </tr>
            ))}
            {!filtered.length && (
              <tr><td colSpan={8} className="text-center py-12">
                <EmptyState title="Aucun article ne correspond" />
              </td></tr>
            )}
          </tbody>
        </table>
      </div>
    </Page>
  );
}

window.Screens = {
  ScreenListeRecettes, ScreenEditRecette,
  ScreenFaconnages, ScreenIncorporations, ScreenArticles,
};
