// ============================================================
// SHELL — sidebar pazienti, header, tab, routing locale
// ============================================================

function bloodFlags(patient) {
  const { BLOOD_REF, latestValues } = window.NefroData;
  const v = latestValues(patient);
  if (!v) return 0;
  return BLOOD_REF.filter((r) => bloodStatus(r, v[r.key]) !== "ok").length;
}

function SideFootMenu({ doctor, onAction }) {
  const [open, setOpen] = useState(false);
  const act = (a) => {setOpen(false);onAction(a);};
  return (
    <div className="side-foot-wrap">
      {open && <div className="menu-scrim" onClick={() => setOpen(false)}></div>}
      {open &&
      <div className="side-menu">
          <button onClick={() => act("edit-profile")}><Icon name="edit" size={15} /> Modifica profilo</button>
          <button onClick={() => act("manage-doctors")}><Icon name="users" size={15} /> Gestione medici</button>
          <button onClick={() => act("credentials")}><Icon name="sliders" size={15} /> Gestione accessi</button>
          <button onClick={() => act("change-password")}><Icon name="droplet" size={15} /> Cambia password</button>
          <button onClick={() => act("logout")}><Icon name="x" size={15} /> Esci</button>
        </div>
      }
      <button className="side-foot side-foot-btn" onClick={() => setOpen((o) => !o)} title="Menu profilo">
        <Avatar nome={doctor.nome} cognome={doctor.cognome} hue={doctor.avatarHue ?? 250} size={36} />
        <div className="side-foot-main">
          <div className="side-foot-name">{doctor.nome} {doctor.cognome}</div>
          <div className="side-foot-role">{doctor.ruolo || "—"}</div>
        </div>
        <Icon name="dots" size={18} />
      </button>
    </div>);

}

function Sidebar({ patients, activeId, onSelect, onNew, view, onView, doctor, onMenuAction }) {
  const [q, setQ] = useState("");
  const list = patients.filter((p) => (p.nome + " " + p.cognome).toLowerCase().includes(q.toLowerCase()));
  return (
    <aside className="sidebar">
      <div className="brand">
        <div className="brand-mark"><Icon name="droplet" size={20} /></div>
        <div className="brand-name">AtaMed<span>AULSS 7 · Nefrologia</span></div>
      </div>
      <div className="side-nav">
        <button className={view === "patients" ? "on" : ""} onClick={() => onView("patients")}>
          <Icon name="users" size={16} /> Pazienti
        </button>
        <button className={view === "recipes" ? "on" : ""} onClick={() => onView("recipes")}>
          <Icon name="bowl" size={16} /> Ricettario
        </button>
        <button className={view === "foods" ? "on" : ""} onClick={() => onView("foods")}>
          <Icon name="leaf" size={16} /> Alimenti
        </button>
      </div>
      <div className="side-search">
        <Icon name="search" size={16} />
        <input placeholder="Cerca paziente…" value={q} onChange={(e) => setQ(e.target.value)} />
      </div>
      <div className="side-label-row">
        <span className="side-label">Pazienti seguiti</span>
        <button className="side-new" onClick={onNew} title="Aggiungi paziente"><Icon name="plus" size={15} /> Nuovo</button>
      </div>
      <div className="patient-list">
        {list.map((p) => {
          const flags = bloodFlags(p);
          return (
            <button key={p.id} className={`patient-item ${p.id === activeId ? "active" : ""}`} onClick={() => onSelect(p.id)}>
              <Avatar nome={p.nome} cognome={p.cognome} hue={p.avatarHue} size={42} />
              <div className="pi-main">
                <div className="pi-name">{p.nome} {p.cognome}</div>
                <div className="pi-meta">
                  {flags > 0 && <span className="pi-flag" style={{ background: "var(--over)" }}></span>}
                  {p.stadio} · {p.eta} anni
                </div>
              </div>
            </button>);

        })}
      </div>
      <SideFootMenu doctor={doctor} onAction={onMenuAction} />
    </aside>);

}

const TABS = [
{ key: "blood", label: "Valori ematici", icon: "droplet" },
{ key: "limits", label: "Limiti nutrizionali", icon: "sliders" },
{ key: "week", label: "Piano settimanale", icon: "calendar" }];


function PatientView({ patient, onChange, onEdit, calStyle }) {
  const [tab, setTab] = useState("week");
  // cache per paziente: { [id]: { giorni, dirty } } — le modifiche restano
  // locali finché non si preme «Salva piano»
  const [weeks, setWeeks] = useState({});
  const [saving, setSaving] = useState(false);
  const E = window.NefroEngine;
  const entry = weeks[patient.id];
  const active = entry?.active || "A";
  const currentGiorni = entry ? (active === "B" ? entry.giorniB : entry.giorni) : null;

  // Genera il piano con l'ottimizzatore OR-Tools sul server (vincoli del
  // paziente garantiti); se non disponibile, generatore euristico locale.
  const generaPiano = async (salt) => {
    try {
      const r = await window.NefroAPI.optimizeWeek(patient.id, salt);
      return r.giorni;
    } catch (e) {
      console.warn("Ottimizzatore non disponibile, uso il generatore locale:", e.message);
      return E.generateWeek(patient, salt);
    }
  };

  // Se esiste un piano salvato su MongoDB si recupera quello,
  // altrimenti se ne genera uno nuovo (non salvato finché non si preme Salva).
  useEffect(() => {
    if (weeks[patient.id]) return;
    let live = true;
    window.NefroAPI.getWeek(patient.id).
    then(async (saved) => {
      if (!live) return;
      if (saved && Array.isArray(saved.giorni) && saved.giorni.length) {
        setWeeks((s) => ({ ...s, [patient.id]: { giorni: saved.giorni, giorniB: saved.giorniB || null, active: "A", dirty: false } }));
      } else {
        const giorni = await generaPiano(0);
        if (live) setWeeks((s) => ({ ...s, [patient.id]: { giorni, giorniB: null, active: "A", dirty: true } }));
      }
    }).
    catch((e) => {
      console.error("Caricamento piano fallito:", e);
      if (live) setWeeks((s) => ({ ...s, [patient.id]: { giorni: E.generateWeek(patient, 0), giorniB: null, active: "A", dirty: true } }));
    });
    return () => {live = false;};
  }, [patient.id]);

  // aggiorna la settimana attualmente selezionata (A oppure B)
  const setWeek = (giorni) => setWeeks((s) => ({ ...s, [patient.id]: { ...s[patient.id], [(s[patient.id]?.active || "A") === "B" ? "giorniB" : "giorni"]: giorni, dirty: true } }));
  const switchWeek = (w) => setWeeks((s) => ({ ...s, [patient.id]: { ...s[patient.id], active: w } }));

  const [regenerating, setRegenerating] = useState(false);
  const regenerateWeek = async () => {
    if (regenerating) return;
    setRegenerating(true);
    try {
      const giorni = await generaPiano(Date.now() % 9999);
      setWeek(giorni);
    } finally {
      setRegenerating(false);
    }
  };

  // Genera DUE settimane diverse (A e B) che si alterneranno per il paziente.
  const generate2Weeks = async () => {
    if (regenerating) return;
    setRegenerating(true);
    try {
      const a = await generaPiano(1);
      const b = await generaPiano(1 + (Date.now() % 9000));
      setWeeks((s) => ({ ...s, [patient.id]: { giorni: a, giorniB: b, active: "A", dirty: true } }));
    } finally {
      setRegenerating(false);
    }
  };

  const saveWeek = async () => {
    if (!entry || !entry.dirty || saving) return;
    setSaving(true);
    try {
      await window.NefroAPI.saveWeek(patient.id, entry.giorni, entry.giorniB);
      setWeeks((s) => ({ ...s, [patient.id]: { ...s[patient.id], dirty: false } }));
    } catch (e) {
      alert("Salvataggio del piano non riuscito: " + e.message);
    } finally {
      setSaving(false);
    }
  };

  // Scarica l'Excel del piano: prima salva le eventuali modifiche,
  // così il file riflette quello che si vede a schermo.
  const downloadWeek = async () => {
    if (!entry) return;
    if (entry.dirty) {
      try {
        await window.NefroAPI.saveWeek(patient.id, entry.giorni, entry.giorniB);
        setWeeks((s) => ({ ...s, [patient.id]: { ...s[patient.id], dirty: false } }));
      } catch (e) {
        alert("Salvataggio del piano non riuscito: " + e.message);
        return;
      }
    }
    try { await window.NefroAPI.downloadWeekXlsx(patient.id); }
    catch (e) { alert("Download non riuscito: " + e.message); }
  };

  const flags = bloodFlags(patient);
  const hasEsami = (patient.esami || []).length > 0;

  return (
    <div className="main">
      <div className="topbar">
        <div className="crumbs">Pazienti <Icon name="chevron" size={13} /> {patient.nome} {patient.cognome}</div>
        <div className="patient-hero">
          <Avatar nome={patient.nome} cognome={patient.cognome} hue={patient.avatarHue} size={58} />
          <div className="hero-main">
            <div className="hero-name-row">
              <div className="hero-name" style={{ fontFamily: "\"Open Sans\"", fontSize: "28px" }}>{patient.nome} {patient.cognome}</div>
              <button className="hero-edit" onClick={() => onEdit(patient)} title="Modifica dati paziente"><Icon name="edit" size={15} /></button>
            </div>
            <div className="hero-sub">
              <Tag tone="neutral">{patient.eta} anni · {patient.sesso === "M" ? "uomo" : "donna"} · {patient.peso} kg</Tag>
              <Tag tone={patient.dialisi ? "over" : "brand"}>{patient.stadio}</Tag>
              {!hasEsami ? <Tag tone="near">nessun prelievo</Tag> :
              flags > 0 ? <Tag tone="over">{flags} valori fuori range</Tag> : <Tag tone="brand">valori nei range</Tag>}
              {patient.diet && <Tag tone="brand">{patient.diet}</Tag>}
            </div>
          </div>
        </div>
      </div>

      <div className="tabbar">
        {TABS.map((t) =>
        <button key={t.key} className={`tab ${tab === t.key ? "active" : ""}`} onClick={() => setTab(t.key)}>
            <Icon name={t.icon} size={16} /> {t.label}
          </button>
        )}
      </div>

      <div className="content">
        {tab === "blood" && <BloodTab patient={patient} onChange={onChange} />}
        {tab === "limits" && <LimitsTab patient={patient} onChange={onChange} />}
        {tab === "week" && (entry && currentGiorni ?
        <WeekTab patient={patient} week={currentGiorni} setWeek={setWeek} calStyle={calStyle}
        dirty={entry.dirty} saving={saving} onSave={saveWeek} onDownload={downloadWeek}
        onRegenerate={regenerateWeek} regenerating={regenerating}
        active={active} hasB={!!entry.giorniB} onSwitch={switchWeek} onGenerate2={generate2Weeks} /> :
        <div className="panel"><p className="panel-sub">Caricamento del piano settimanale…</p></div>)}
      </div>
    </div>);

}

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "calStyle": "grid",
  "cardDetail": "full"
} /*EDITMODE-END*/;

function App() {
  // Stato iniziale caricato dal backend in bootstrap() prima del render
  const [patients, setPatients] = useState(window.NefroData.PATIENTS);
  const [activeId, setActiveId] = useState(window.NefroData.PATIENTS[0]?.id ?? null);
  const [view, setView] = useState("patients"); // "patients" | "recipes" | "foods" | "doctors"
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [modal, setModal] = useState(null); // {mode:"new"} | {mode:"edit", patient}

  // —— Medici: profilo corrente (ricordato in localStorage) e gestione ——
  const [doctors, setDoctors] = useState(window.NefroData.DOCTORS);
  const [currentDocId, setCurrentDocId] = useState(() => window.NefroData.ME?.id || localStorage.getItem("nefroDoctor") || window.NefroData.DOCTORS[0]?.id);
  const [docModal, setDocModal] = useState(null); // {mode:"new"} | {mode:"edit", doctor}
  const currentDoctor = doctors.find((d) => d.id === currentDocId) || doctors[0] || { nome: "—", cognome: "", ruolo: "" };

  const useDoctor = (id) => {setCurrentDocId(id);localStorage.setItem("nefroDoctor", id);};

  const saveDoctor = async (d, isNew) => {
    try {
      isNew ? await window.NefroAPI.createDoctor(d) : await window.NefroAPI.updateDoctor(d);
    } catch (e) {
      alert("Salvataggio non riuscito: " + e.message);
      return;
    }
    setDoctors((ds) => isNew ? [...ds, d] : ds.map((x) => x.id === d.id ? d : x));
    setDocModal(null);
  };

  const deleteDoctor = async (d) => {
    if (doctors.length <= 1) {alert("Deve restare almeno un medico.");return;}
    if (!confirm(`Eliminare il profilo di ${d.nome} ${d.cognome}?`)) return;
    try {
      await window.NefroAPI.deleteDoctor(d.id);
    } catch (e) {
      alert("Eliminazione non riuscita: " + e.message);
      return;
    }
    const resto = doctors.filter((x) => x.id !== d.id);
    setDoctors(resto);
    if (currentDocId === d.id) useDoctor(resto[0].id);
    setDocModal(null);
  };

  const onMenuAction = async (a) => {
    if (a === "edit-profile") setDocModal({ mode: "edit", doctor: currentDoctor });
    if (a === "manage-doctors") setView("doctors");
    if (a === "credentials") setView("credentials");
    if (a === "logout") window.NefroAPI.logout();
    if (a === "change-password") {
      const pw = prompt("Nuova password (min 4 caratteri):");
      if (!pw) return;
      try { await window.NefroAPI.changeMyPassword(pw); alert("Password aggiornata."); }
      catch (e) { alert("Non riuscito: " + e.message); }
    }
  };

  const active = patients.find((p) => p.id === activeId);

  const updatePatient = (np) => {
    setPatients((ps) => ps.map((p) => p.id === np.id ? np : p));
    window.NefroAPI.updatePatient(np).catch((e) => console.error("Salvataggio paziente fallito:", e));
  };

  const savePatient = async (p) => {
    const exists = patients.some((x) => x.id === p.id);
    try {
      exists ? await window.NefroAPI.updatePatient(p) : await window.NefroAPI.createPatient(p);
    } catch (e) {
      alert("Salvataggio non riuscito: " + e.message);
      return;
    }
    setPatients((ps) => exists ? ps.map((x) => x.id === p.id ? p : x) : [...ps, p]);
    setActiveId(p.id);
    setModal(null);
  };

  return (
    <div className="app" data-detail={t.cardDetail}>
      <Sidebar patients={patients} activeId={activeId} view={view} onView={setView}
      doctor={currentDoctor} onMenuAction={onMenuAction}
      onSelect={(id) => {setActiveId(id);setView("patients");}}
      onNew={() => {setView("patients");setModal({ mode: "new" });}} />
      {view === "recipes" ?
      <RecipesView /> :
      view === "foods" ?
      <FoodsView /> :
      view === "doctors" ?
      <DoctorsView doctors={doctors} currentId={currentDoctor.id} onUse={useDoctor}
      onEdit={(d) => setDocModal({ mode: "edit", doctor: d })} onNew={() => setDocModal({ mode: "new" })} /> :
      view === "credentials" ?
      <CredentialsView doctors={doctors} patients={patients} currentDocId={currentDoctor.id}
      onSaved={(kind, id, username) => kind === "doctor"
        ? setDoctors((ds) => ds.map((d) => d.id === id ? { ...d, username } : d))
        : setPatients((ps) => ps.map((p) => p.id === id ? { ...p, username } : p))} /> :
      active ?
      <PatientView patient={active} onChange={updatePatient} onEdit={(p) => setModal({ mode: "edit", patient: p })} calStyle={t.calStyle} /> :
      <div className="main"><div className="content"><div className="empty-state">
            <div className="empty-orb"><Icon name="users" size={22} /></div>
            <p>Nessun paziente in archivio. Crea il primo paziente per iniziare.</p>
            <button className="btn btn-primary" onClick={() => setModal({ mode: "new" })}><Icon name="plus" size={16} /> Nuovo paziente</button>
          </div></div></div>}
      {modal && <PatientModal mode={modal.mode} patient={modal.patient} onSave={savePatient} onClose={() => setModal(null)} />}
      {docModal && <DoctorModal mode={docModal.mode} doctor={docModal.doctor} canDelete={doctors.length > 1}
      onSave={saveDoctor} onDelete={deleteDoctor} onClose={() => setDocModal(null)} />}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Calendario" />
        <TweakRadio label="Vista" value={t.calStyle}
        options={[{ value: "grid", label: "Griglia" }, { value: "list", label: "Lista" }]}
        onChange={(v) => setTweak("calStyle", v)} />
        <TweakRadio label="Dettaglio card" value={t.cardDetail}
        options={[{ value: "full", label: "Completo" }, { value: "compact", label: "Compatto" }]}
        onChange={(v) => setTweak("cardDetail", v)} />
      </TweaksPanel>
    </div>);

}

window.App = App;