/* Poarta pilotului: versiune -> cod de acces -> identitate -> aplicatie.
   Scrie DIRECT in localStorage, iar App citeste store-ul cand se monteaza (adica dupa ce
   poarta se deschide) - asa nu e nevoie de niciun canal de comunicare intre cele doua
   radacini de stare.

   Regula care nu se incalca: catre server pleaca DOAR metadate (cine, cand, cat, ce versiune).
   Niciun plan, nicio bifa, niciun raspuns. Serverul respinge orice camp in plus. */

const PILOT_CHEIE_STORE = "prp-credinte-proto-v1";
const PILOT_CHEIE_ACCES = "prp-pilot-acces";
const PILOT_COD = "PRP2026";     /* bariera, NU securitate: ruland in browser, e vizibil oricui */
const PILOT_API = "/api/ev";

function pilotCitesteStore() {
  try { return JSON.parse(localStorage.getItem(PILOT_CHEIE_STORE) || "{}"); } catch (e) { return {}; }
}

function pilotScrieStore(s) {
  try { localStorage.setItem(PILOT_CHEIE_STORE, JSON.stringify(s)); } catch (e) { /* plin: ignoram */ }
}

function pilotIdNou() {
  if (window.crypto && window.crypto.randomUUID) return window.crypto.randomUUID();
  return "id-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
}

/* Scrie in ACELASI camp `consola` pe care il foloseste aplicatia, ca poarta veche
   (`consolaOk`: nume + dataStart) sa fie satisfacuta de aceleasi date - altfel participantul
   ar trece prin doua ecrane de intrare care cer acelasi lucru. */
function pilotScrieConsola(campuri) {
  const s = pilotCitesteStore();
  s.consola = Object.assign(
    { nume: "", dataStart: "", consultant: "Dr. Petre Nicolae", telefon: "", email: "", obs: "" },
    s.consola, campuri);
  if (!s.pilotId) s.pilotId = pilotIdNou();
  pilotScrieStore(s);
  return s;
}

/* ── Ecrane ────────────────────────────────────────────────────── */

function PilotEcran({ titlu, children }) {
  return (
    <div className="reset-ecran">
      <div className="panel" style={{ maxWidth: 520, width: "100%" }}>
        <div className="brand" style={{ paddingTop: 0 }}>
          <img src="logo-prp.png" alt="Logo PRP" className="brand-logo" style={{ height: 84 }} />
          <div className="brand-prp">People Reconstruction Process</div>
        </div>
        <h1 className="hero-salut" style={{ fontSize: "var(--m-fs-6)", marginBottom: 8 }}>{titlu}</h1>
        {children}
      </div>
    </div>
  );
}

/* Trecerea pe versiunea noua: intai copie locala a datelor, apoi se sterge service worker-ul
   vechi si se reincarca. Datele raman in acelasi sertar - adresa nu se schimba niciodata. */
async function pilotActualizeaza() {
  /* Copia se face INTAI: daca ceva merge prost in pasii urmatori, datele sunt deja puse deoparte. */
  window.PRP_PILOT.faBackupLocal(localStorage, PILOT_CHEIE_STORE, window.PRP_VERSIUNE || "necunoscuta");
  try {
    if (navigator.serviceWorker) {
      const reg = await navigator.serviceWorker.getRegistration();
      if (reg) {
        await reg.update();                       /* aduce versiunea noua daca nu e deja in asteptare */
        const nou = reg.waiting || reg.installing;
        if (nou) {
          /* asteptam sa fie gata de preluare, apoi ii cerem sa preia - fara asta, un
             service worker inca in instalare ar ignora mesajul si am reincarca degeaba */
          await new Promise((gata) => {
            if (nou.state === "installed") return gata();
            nou.addEventListener("statechange", () => { if (nou.state === "installed") gata(); });
            setTimeout(gata, 8000);               /* plasa: nu blocam participantul la nesfarsit */
          });
          /* `skipWaiting` e asincron: daca reincarcam imediat dupa mesaj, pagina e servita
             tot de workerul VECHI si abia a doua reincarcare aduce versiunea noua (masurat
             25.07). Asteptam schimbarea efectiva a controlorului, ca un singur clic sa ajunga. */
          const preluat = new Promise((gata) => {
            navigator.serviceWorker.addEventListener("controllerchange", gata, { once: true });
            setTimeout(gata, 8000);
          });
          nou.postMessage({ tip: "preia-controlul" });
          await preluat;
        } else {
          /* nicio versiune in asteptare: stergem inregistrarea, ca reincarcarea sa ia totul de la server */
          await reg.unregister();
        }
      }
    }
  } catch (e) { /* fara service worker: reincarcarea simpla e suficienta */ }
  location.reload();
}

function PilotEcranUpdate() {
  const [lucreaza, setLucreaza] = React.useState(false);
  return (
    <PilotEcran titlu="Trebuie să actualizezi instrumentul">
      <p className="muted small">
        A apărut o versiune nouă, iar cea de pe calculatorul tău nu mai poate fi folosită.
        Datele tale rămân neatinse: înainte de actualizare se salvează automat o copie,
        tot aici, pe calculatorul tău.
      </p>
      <button className="btn btn-primary mt-14" disabled={lucreaza}
        onClick={() => { setLucreaza(true); pilotActualizeaza(); }}>
        {lucreaza ? "Se actualizează..." : "Actualizează acum"}
      </button>
    </PilotEcran>
  );
}

/* Versiune mai veche, dar inca acceptata: nu blocam pe nimeni pentru o corectura marunta. */
function PilotBanner() {
  const [ascuns, setAscuns] = React.useState(false);
  if (ascuns) return null;
  return (
    <div className="row small" style={{
      position: "fixed", left: 0, right: 0, bottom: 0, zIndex: 70,
      background: "var(--m-navy-s)", color: "var(--m-navy)",
      borderTop: "1px solid var(--m-border)", padding: "8px 14px", gap: 12,
    }}>
      <span className="grow">Există o versiune nouă a instrumentului.</span>
      <button className="btn btn-sm btn-primary" onClick={pilotActualizeaza}>Actualizează</button>
      <button className="btn btn-sm btn-ghost" onClick={() => setAscuns(true)}>Mai târziu</button>
    </div>
  );
}

function PilotEcranCod({ onOk }) {
  const [cod, setCod] = React.useState("");
  const [gresit, setGresit] = React.useState(false);
  const trimite = (e) => {
    e.preventDefault();
    if (cod.trim().toUpperCase() === PILOT_COD) {
      try { localStorage.setItem(PILOT_CHEIE_ACCES, "1"); } catch (err) { /* privat: continuam */ }
      onOk();
    } else {
      setGresit(true);
    }
  };
  return (
    <PilotEcran titlu="Codul de acces">
      <p className="muted small">Introdu codul primit împreună cu linkul.</p>
      <form onSubmit={trimite} className="stack-14 mt-14">
        <input className="input" value={cod} autoFocus aria-label="Cod de acces"
          onChange={(e) => { setCod(e.target.value); setGresit(false); }} />
        {gresit && <div className="small" style={{ color: "var(--m-bad)" }}>Codul nu este corect.</div>}
        <button className="btn btn-primary" type="submit">Intră</button>
      </form>
    </PilotEcran>
  );
}

function PilotEcranIdentitate({ onOk }) {
  const c = pilotCitesteStore().consola || {};
  const [nume, setNume] = React.useState(c.nume || "");
  const [email, setEmail] = React.useState(c.email || "");
  const [data, setData] = React.useState(c.dataStart || new Date().toISOString().slice(0, 10));
  const [acord, setAcord] = React.useState(true);
  const valid = nume.trim().length >= 3
    && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim())
    && !!data;

  const trimite = (e) => {
    e.preventDefault();
    if (!valid) return;
    const s = pilotScrieConsola({
      nume: nume.trim(), email: email.trim().toLowerCase(), dataStart: data,
    });
    s.pilotAcord = acord;
    pilotScrieStore(s);
    onOk();
  };

  return (
    <PilotEcran titlu="Să începem">
      <p className="muted small">
        Instrumentul este al tău: tot ce scrii aici rămâne pe calculatorul acesta și nu pleacă
        nicăieri. Avem nevoie doar de numele și de emailul tău, ca să știm cine face parte din program.
      </p>
      <form onSubmit={trimite} className="stack-14 mt-14">
        <label className="field"><span className="field-label">Numele tău</span>
          <input className="input" value={nume} autoFocus onChange={(e) => setNume(e.target.value)} /></label>
        <label className="field"><span className="field-label">Email</span>
          <input className="input" type="email" value={email} onChange={(e) => setEmail(e.target.value)} /></label>
        <label className="field"><span className="field-label">Data de început a procesului</span>
          <input className="input" type="date" value={data} onChange={(e) => setData(e.target.value)} /></label>
        <label className="row small" style={{ alignItems: "flex-start", gap: 8 }}>
          <input type="checkbox" checked={acord} style={{ marginTop: 3 }}
            onChange={(e) => setAcord(e.target.checked)} />
          <span>
            Sunt de acord să se înregistreze când deschid instrumentul și cât timp îl folosesc.
            Conținutul a ceea ce scriu NU se trimite și nu poate fi citit de nimeni altcineva.
          </span>
        </label>
        <button className="btn btn-primary" type="submit" disabled={!valid}>Intră în instrument</button>
      </form>
    </PilotEcran>
  );
}

/* ── Instalarea: automata unde se poate, o singura instructiune unde nu ── */

/* Deja instalata = aplicatia ruleaza in fereastra proprie, fara bara de adrese. */
function pilotEsteInstalata() {
  try {
    return window.matchMedia("(display-mode: standalone)").matches
      || window.navigator.standalone === true;
  } catch (e) {
    return false;
  }
}

/* Instructiunea se da DOAR unde browserul nu ofera instalare programatica, si e specifica
   browserului real - un manual cu toate variantele nu il citeste nimeni. */
function pilotInstructiuneManuala() {
  const ua = navigator.userAgent;
  const eIOS = /iPhone|iPad|iPod/.test(ua);
  const eSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(ua);
  if (eIOS) return "Apasă butonul Partajează din bara de jos, apoi „Adaugă pe ecranul principal”.";
  if (eSafari) return "Din meniul Fișier alege „Adaugă în Dock”.";
  if (/Firefox/.test(ua)) return null;   /* Firefox nu instalează aplicații web; nu il batem la cap */
  return null;
}

function PilotInstalare({ compact }) {
  const [prompt, setPrompt] = React.useState(() => window.__promptInstalare || null);
  const [instalata, setInstalata] = React.useState(pilotEsteInstalata);
  const [ascuns, setAscuns] = React.useState(() => {
    try { return localStorage.getItem("prp-pilot-instalare-ascuns") === "1"; } catch (e) { return false; }
  });
  const [lucreaza, setLucreaza] = React.useState(false);

  React.useEffect(() => {
    const laDisponibil = () => setPrompt(window.__promptInstalare);
    const laInstalat = () => { setPrompt(null); setInstalata(true); };
    window.addEventListener("prp-instalabil", laDisponibil);
    window.addEventListener("prp-instalat", laInstalat);
    return () => {
      window.removeEventListener("prp-instalabil", laDisponibil);
      window.removeEventListener("prp-instalat", laInstalat);
    };
  }, []);

  const instaleaza = async () => {
    if (!prompt) return;
    setLucreaza(true);
    try {
      prompt.prompt();
      const rez = await prompt.userChoice;
      if (rez && rez.outcome === "accepted") { setInstalata(true); }
      window.__promptInstalare = null;
      setPrompt(null);
    } catch (e) { /* utilizatorul a inchis dialogul */ }
    setLucreaza(false);
  };

  const ascunde = () => {
    try { localStorage.setItem("prp-pilot-instalare-ascuns", "1"); } catch (e) { /* privat */ }
    setAscuns(true);
  };

  if (instalata) {
    return compact
      ? <div className="small muted">Aplicația este instalată pe acest calculator.</div>
      : null;
  }

  const manual = prompt ? null : pilotInstructiuneManuala();
  if (!prompt && !manual) return null;          /* browser fara instalare: nu spunem nimic */
  if (ascuns && !compact) return null;

  const continut = (
    <>
      <span className="grow">
        {prompt
          ? "Instalează instrumentul pe calculatorul tău: se deschide cu o iconiță și merge și fără internet."
          : manual}
      </span>
      {prompt && (
        <button className="btn btn-sm btn-primary" onClick={instaleaza} disabled={lucreaza}>
          {lucreaza ? "Se instalează..." : "Instalează"}
        </button>
      )}
      {!compact && <button className="btn btn-sm btn-ghost" onClick={ascunde}>Mai târziu</button>}
    </>
  );

  if (compact) return <div className="row small" style={{ gap: 10 }}>{continut}</div>;

  return (
    <div className="row small" style={{
      position: "fixed", left: 0, right: 0, bottom: 0, zIndex: 65,
      background: "var(--m-gold-s)", color: "var(--m-gold-text)",
      borderTop: "1px solid var(--m-border)", padding: "8px 14px", gap: 12,
    }}>
      {continut}
    </div>
  );
}

/* ── Telemetria: prezenta si timp, nimic altceva ───────────────── */

function PilotTelemetrie() {
  React.useEffect(() => {
    if (pilotCitesteStore().pilotAcord === false) return;   /* acord retras: instrumentul merge, masurarea nu */

    const coada = window.PRP_PILOT.Coada(localStorage);
    const identitate = () => {
      const s = pilotCitesteStore();
      const c = s.consola || {};
      return {
        id: s.pilotId || "", nume: c.nume || "", email: c.email || "",
        versiune: window.PRP_VERSIUNE || "",
      };
    };
    const descarca = async () => {
      const ev = coada.toate();
      if (!ev.length) return;
      try {
        const r = await fetch(PILOT_API, {
          method: "POST", headers: { "Content-Type": "application/json" },
          body: JSON.stringify(Object.assign(identitate(), { evenimente: ev })),
        });
        if (r.ok) coada.goleste();
      } catch (e) { /* fara retea: raman in coada pana data viitoare */ }
    };

    coada.adauga({ tip: "deschidere", t: Date.now() });
    descarca();

    const puls = window.PRP_PILOT.Puls({
      acum: () => Date.now(),
      trimite: (ev) => coada.adauga(ev),
    });
    puls.interactiune();
    const peInteractiune = () => puls.interactiune();
    const evenimenteUI = ["pointerdown", "keydown", "wheel"];
    evenimenteUI.forEach((e) => window.addEventListener(e, peInteractiune, { passive: true }));

    const tick = setInterval(() => puls.tick(document.visibilityState === "visible"), 60000);
    const sincron = setInterval(descarca, 300000);
    const laRevenire = () => descarca();
    window.addEventListener("online", laRevenire);

    /* sendBeacon e singurul care mai apuca sa plece la inchiderea ferestrei */
    const laPlecare = () => {
      coada.adauga({ tip: "plecare", t: Date.now() });
      try {
        const corp = JSON.stringify(Object.assign(identitate(), { evenimente: coada.toate() }));
        if (navigator.sendBeacon(PILOT_API, new Blob([corp], { type: "application/json" }))) {
          coada.goleste();
        }
      } catch (e) { /* raman in coada */ }
    };
    window.addEventListener("pagehide", laPlecare);

    return () => {
      clearInterval(tick); clearInterval(sincron);
      puls.opreste();
      evenimenteUI.forEach((e) => window.removeEventListener(e, peInteractiune));
      window.removeEventListener("online", laRevenire);
      window.removeEventListener("pagehide", laPlecare);
    };
  }, []);
  return null;
}

/* ── Poarta ────────────────────────────────────────────────────── */

/* Ordinea conteaza: versiunea se verifica PRIMA, ca o versiune retrasa sa nu mai poata
   nici colecta, nici scrie in store. */
function PilotGate({ children }) {
  const [stare, setStare] = React.useState("verifica");
  const [pas, setPas] = React.useState(0);   /* re-randare dupa ce s-a scris in localStorage */

  React.useEffect(() => {
    let anulat = false;
    fetch("versiune.json?t=" + Date.now(), { cache: "no-store" })
      .then((r) => r.json())
      .then((srv) => { if (!anulat) setStare(window.PRP_PILOT.stareVersiune(window.PRP_VERSIUNE, srv)); })
      .catch(() => { if (!anulat) setStare("ok"); })   /* fara retea: se lucreaza mai departe */;
    return () => { anulat = true; };
  }, []);

  if (stare === "verifica") return null;
  if (stare === "blocat") return <PilotEcranUpdate />;

  let acces = null;
  try { acces = localStorage.getItem(PILOT_CHEIE_ACCES); } catch (e) { /* privat */ }
  if (acces !== "1") return <PilotEcranCod onOk={() => setPas((n) => n + 1)} />;

  const c = pilotCitesteStore().consola || {};
  if (!c.nume || !c.email) return <PilotEcranIdentitate onOk={() => setPas((n) => n + 1)} />;

  return (
    <>
      {children}
      <PilotTelemetrie />
      {/* bannerul de update are prioritate: cand exista versiune noua, nu il incarcam si cu instalarea */}
      {stare === "optional" ? <PilotBanner /> : <PilotInstalare />}
    </>
  );
}

/* ── Ecranul "Datele mele" ─────────────────────────────────────── */

function PilotDateleMele() {
  const s = pilotCitesteStore();
  const c = s.consola || {};
  const [acord, setAcord] = React.useState(s.pilotAcord !== false);

  const schimbaAcord = (v) => {
    const st = pilotCitesteStore();
    st.pilotAcord = v;
    pilotScrieStore(st);
    setAcord(v);
    if (!v) {
      /* oprirea are efect imediat: golim si ce astepta in coada */
      window.PRP_PILOT.Coada(localStorage).goleste();
    }
  };

  const stergeTot = () => {
    if (!confirm("Se șterg TOATE datele tale de pe acest calculator. Nu se mai pot recupera. Continui?")) return;
    if (!confirm("Ești sigur? Dacă nu ai exportat datele, fă-o întâi.")) return;
    try {
      Object.keys(localStorage)
        .filter((k) => k.indexOf("prp-credinte-proto") === 0 || k.indexOf("prp-pilot") === 0)
        .forEach((k) => localStorage.removeItem(k));
    } catch (e) { /* ignoram */ }
    location.reload();
  };

  const backupuri = (() => {
    try {
      return Object.keys(localStorage).filter((k) => k.indexOf(PILOT_CHEIE_STORE + ".bak-") === 0)
        .map((k) => k.split(".bak-")[1]).sort();
    } catch (e) { return []; }
  })();

  return (
    <div className="page stack-14">
      <div className="panel">
        <div className="sect-label">Ce știm despre tine</div>
        <table className="tbl">
          <tbody>
            <tr><td>Nume</td><td>{c.nume || "-"}</td></tr>
            <tr><td>Email</td><td>{c.email || "-"}</td></tr>
            <tr><td>Versiunea instrumentului</td><td>{window.PRP_VERSIUNE || "necunoscută"}</td></tr>
            <tr><td>Momentele în care deschizi instrumentul și cât timp stai</td>
                <td>{acord ? "se înregistrează" : "nu se înregistrează"}</td></tr>
          </tbody>
        </table>
        <p className="muted small mt-14">
          Nimic din ce scrii în instrument nu pleacă de pe acest calculator: nici planurile,
          nici bifele, nici răspunsurile la chestionare. Nu le putem citi.
        </p>
      </div>

      <div className="panel">
        <div className="sect-label">Controalele tale</div>
        <label className="row small" style={{ alignItems: "flex-start", gap: 8 }}>
          <input type="checkbox" checked={acord} style={{ marginTop: 3 }}
            onChange={(e) => schimbaAcord(e.target.checked)} />
          <span>
            Se poate înregistra când deschid instrumentul și cât îl folosesc. Dacă debifezi,
            înregistrarea se oprește imediat, iar instrumentul merge mai departe la fel.
          </span>
        </label>
        <div className="row mt-18">
          <button className="btn btn-ghost" onClick={stergeTot}>
            Șterge toate datele mele de pe acest calculator
          </button>
        </div>
        <p className="muted small mt-14">
          Pentru ștergerea din evidența programului, scrie consultantului tău.
        </p>
      </div>

      <div className="panel">
        <div className="sect-label">Instalarea pe acest calculator</div>
        <PilotInstalare compact />
        <p className="muted small mt-14">
          Instalată, aplicația se deschide cu o iconiță proprie și funcționează și fără internet.
          Datele rămân aceleași, indiferent dacă o deschizi din iconiță sau din link.
        </p>
      </div>

      <div className="panel">
        <div className="sect-label">Copii de siguranță pe acest calculator</div>
        {backupuri.length === 0
          ? <div className="empty"><span className="empty-title">Încă nicio copie</span>
              <span className="small">Se creează automat câte una înainte de fiecare actualizare.</span></div>
          : <ul className="small muted" style={{ margin: 0, paddingLeft: 18 }}>
              {backupuri.map((v) => <li key={v}>copie de dinaintea versiunii {v}</li>)}
            </ul>}
        <p className="muted small mt-14">
          Copiile stau tot aici, la tine. Ele nu te apără dacă ștergi datele browserului sau
          schimbi calculatorul: pentru asta, exportă-ți procesul din Consolă și păstrează fișierul.
        </p>
      </div>
    </div>
  );
}

window.PilotGate = PilotGate;
window.PilotDateleMele = PilotDateleMele;
window.pilotCitesteStore = pilotCitesteStore;
window.IcScut = (p) => (
  <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor"
    strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}>
    <path d="M12 3l7 3v6c0 4.5-3 7.7-7 9-4-1.3-7-4.5-7-9V6l7-3z" />
    <path d="M9 12l2 2 4-4" />
  </svg>
);
