/* technici.jsx — "Správa technikov": admin vyhľadá kohokoľvek z firmy a pridá mu rolu,
   alebo upraví/deaktivuje existujúceho technika. Log zmien (kto/kedy/čo) je samostatný
   SharePoint zoznam (LIST_ID.TECHNICI_LOG) — kým nie je založený, appka log jednoducho
   nezobrazuje ani doň nezapisuje (best-effort, viď graph.jsx zapisDoLoguTechnikov).

   VEDOMÝ KOMPROMIS (rozhodnutie Jakuba, 2026-09-03): nový technik sa zakladá BEZ vyplneného
   SharePoint Person poľa Konto — appka ho nevie cez Graph vyriešiť pre niekoho, kto ešte
   nikdy nemal k site-u žiadny vzťah (viď komentár pri createTechnik v graph.jsx). Appka
   samotná (prihlásenie, rola, priraďovanie) funguje aj bez neho — jediný dôsledok je
   prázdne natívne SharePoint pole "Priradený technik" na jeho tiketoch, kým mu ho niekto
   raz ručne nenastaví priamo v SharePointe. */

const TC_ROLE = ["Technik", "Admin"];

// Jedna položka v zozname existujúcich technikov — meno, avatar, prepínač role a aktivity.
// Zmena sa zapisuje priamo (žiadny optimistický lokálny stav ako pri tiketoch): editácie
// technikov sú zriedkavé, jednoduchšie a menej rizikové je počkať na skutočný zápis a potom
// dáta obnoviť (onZmenene), než znova stavať rollback-pri-zlyhaní logiku z app.jsx.
function TcRiadok({ t, onZmena }) {
  const [ukladaSa, setUkladaSa] = useState(false);
  const [chyba, setChyba] = useState("");

  const zapis = async (patch, logAkcia, logDetail) => {
    setUkladaSa(true);
    setChyba("");
    try {
      await window.HELPDESK_GRAPH.patchTechnik(t.id, patch);
      await onZmena(t.meno, logAkcia, logDetail);
    } catch (e) {
      setChyba(e.message || String(e));
    } finally {
      setUkladaSa(false);
    }
  };

  const zmenRolu = (novaRola) => {
    if (novaRola === t.rola) return;
    zapis({ Rola: novaRola }, "Zmena role", "Rola: " + t.rola + " → " + novaRola);
  };
  const prepniAktivitu = () => {
    const novaAktivita = !t.aktivny;
    zapis({ Aktivny: novaAktivita }, novaAktivita ? "Aktivovaný" : "Deaktivovaný", null);
  };

  return (
    <tr style={{ borderBottom: "1px solid var(--stroke)", opacity: t.aktivny ? 1 : 0.55 }}>
      <td style={{ padding: "10px 12px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <Avatar meno={t.meno} farba={t.farba} size={30} photoKey={t.meno} />
          <div>
            <div style={{ fontWeight: 700, fontSize: 13.5 }}>{t.meno}</div>
            {!t.aktivny && <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>Neaktívny</div>}
          </div>
        </div>
      </td>
      <td style={{ padding: "10px 12px" }}>
        <select value={t.rola} onChange={(e) => zmenRolu(e.target.value)} disabled={ukladaSa || !t.aktivny} style={{
          padding: "6px 9px", fontSize: 13, borderRadius: "var(--radius-sm)", border: "1px solid var(--stroke-strong)",
          background: "var(--surface)", color: "var(--text)", fontFamily: "inherit",
        }}>
          {TC_ROLE.map((r) => <option key={r} value={r}>{r === "Admin" ? "Administrátor" : "Technik"}</option>)}
        </select>
      </td>
      <td style={{ padding: "10px 12px", textAlign: "right" }}>
        {chyba && <div style={{ fontSize: 11.5, color: "var(--red)", marginBottom: 4, maxWidth: 220, marginLeft: "auto" }}>{chyba}</div>}
        {/* Rôzne `key` na oboch vetvách (nie len rôzny `kind`) — React porovnáva podľa typu
            komponentu na danej pozícii (obe vetvy sú <Btn>), nie podľa vetvy v ternárnom
            výraze, takže by inak stále išlo o AKTUALIZÁCIU toho istého uzla. Btn interne
            mergne {...base, ...kinds[kind]} do jedného style objektu; keby ten istý DOM uzol
            prepínal kind "default" (má borderColor) ↔ "primary" (nemá), React by pri každom
            prekreslení musel borderColor raz pridávať a raz uberať a v deve na to varuje
            (miešanie skratky "border" a "borderColor"). Rôzny key = React uzol zbúra
            a postaví nový namiesto aktualizácie, takže niet čo diffovať. */}
        {t.aktivny ? (
          <Btn key="deaktivovat" kind="default" size="sm" onClick={prepniAktivitu} disabled={ukladaSa}>Deaktivovať</Btn>
        ) : (
          <Btn key="aktivovat" kind="primary" size="sm" onClick={prepniAktivitu} disabled={ukladaSa}>Aktivovať</Btn>
        )}
      </td>
    </tr>
  );
}

// Vyhľadanie a pridanie nového technika — jedna osoba naraz (na rozdiel od PersonChips
// v ui.jsx, ktorý zbiera pole mien pre "Týka sa"/"S kým"). Rovnaký debounce vzor (300 ms,
// min. 2 znaky), len s jedným vybraným výsledkom namiesto zoznamu chipov.
function TcPridatTechnika({ technici, jaMeno, jaEmail, onPridany }) {
  const [text, setText] = useState("");
  const [navrhy, setNavrhy] = useState([]);
  const [hladam, setHladam] = useState(false);
  const [vybrany, setVybrany] = useState(null); // { meno, email }
  const [rola, setRola] = useState("Technik");
  const [ukladaSa, setUkladaSa] = useState(false);
  const [chyba, setChyba] = useState("");
  const debRef = useRef(null);

  useEffect(() => {
    if (debRef.current) clearTimeout(debRef.current);
    const q = text.trim();
    if (vybrany || q.length < 2) { setNavrhy([]); setHladam(false); return; }
    setHladam(true);
    debRef.current = setTimeout(() => {
      window.HELPDESK_GRAPH.searchUsers(q)
        .then((vysledky) => setNavrhy(vysledky))
        .catch(() => setNavrhy([]))
        .finally(() => setHladam(false));
    }, 300);
    return () => clearTimeout(debRef.current);
  }, [text, vybrany]);

  // Podľa mena (appka nemá inú spoľahlivú zhodu pre niekoho, kto ešte nemá Konto) — rovnaký
  // spôsob párovania ako všade inde v appke (najdiTechnikaPodlaPersonPola v data.jsx).
  const uzExistuje = vybrany && technici.find((t) => t.meno.toLowerCase() === vybrany.meno.toLowerCase());

  const pridat = async () => {
    if (!vybrany) return;
    setUkladaSa(true);
    setChyba("");
    try {
      if (uzExistuje && !uzExistuje.aktivny) {
        // Osoba je v zozname, len neaktívna — aktivovať namiesto duplicitného pridania.
        await window.HELPDESK_GRAPH.patchTechnik(uzExistuje.id, { Rola: rola, Aktivny: true });
        await onPridany(uzExistuje.meno, "Aktivovaný", "Znovu pridaný ako " + rola);
      } else {
        await window.HELPDESK_GRAPH.createTechnik({ Title: vybrany.meno, Rola: rola, Aktivny: true });
        await onPridany(vybrany.meno, "Pridaný", "Pridaný ako " + rola);
      }
      setText(""); setVybrany(null); setRola("Technik");
    } catch (e) {
      setChyba(e.message || String(e));
    } finally {
      setUkladaSa(false);
    }
  };

  return (
    <div style={{ padding: "var(--pf-card-pad, 16px)", background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)" }}>
      <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 10 }}>Pridať technika</div>
      <div style={{ display: "flex", gap: 10, flexWrap: "wrap", alignItems: "flex-start" }}>
        <div style={{ position: "relative", flex: "1 1 240px", minWidth: 220 }}>
          {vybrany ? (
            <div style={{
              display: "flex", alignItems: "center", gap: 8, padding: "7px 10px", borderRadius: "var(--radius-sm)",
              border: "1px solid var(--stroke-strong)", background: "var(--surface-2)",
            }}>
              <Avatar meno={vybrany.meno} farba="var(--accent)" size={22} photoKey={vybrany.meno} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 700, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{vybrany.meno}</div>
                <div style={{ fontSize: 11, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{vybrany.email}</div>
              </div>
              <button onClick={() => setVybrany(null)} title="Zrušiť výber" style={{ border: "none", background: "transparent", color: "var(--text-3)", display: "inline-flex" }}>
                <Icon name="close" size={14} />
              </button>
            </div>
          ) : (
            <input value={text} onChange={(e) => setText(e.target.value)} placeholder="Hľadať meno v M365 adresári…" style={{
              width: "100%", padding: "7px 10px", fontSize: 13, borderRadius: "var(--radius-sm)", border: "1px solid var(--stroke-strong)",
              background: "var(--surface-2)", color: "var(--text)", fontFamily: "inherit", boxSizing: "border-box",
            }} />
          )}
          {!vybrany && text.trim().length >= 2 && (
            <div style={{
              position: "absolute", top: "100%", left: 0, right: 0, marginTop: 4, zIndex: 20,
              background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-sm)",
              boxShadow: "var(--shadow-md)", maxHeight: 220, overflowY: "auto",
            }}>
              {hladam ? (
                <div style={{ padding: 10, fontSize: 12.5, color: "var(--text-3)" }}>Hľadám…</div>
              ) : navrhy.length ? navrhy.map((u) => (
                <button key={u.email || u.meno} onClick={() => { setVybrany(u); setNavrhy([]); }} style={{
                  display: "flex", alignItems: "center", gap: 8, width: "100%", padding: "8px 10px", border: "none",
                  background: "transparent", textAlign: "left", fontSize: 13,
                }} onMouseEnter={(e) => e.currentTarget.style.background = "var(--surface-3)"} onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}>
                  <Avatar meno={u.meno} farba="var(--accent)" size={22} photoKey={u.meno} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{u.meno}</div>
                    <div style={{ fontSize: 11, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{u.email}</div>
                  </div>
                </button>
              )) : (
                <div style={{ padding: 10, fontSize: 12.5, color: "var(--text-3)" }}>Nikto sa nenašiel.</div>
              )}
            </div>
          )}
        </div>
        <select value={rola} onChange={(e) => setRola(e.target.value)} disabled={ukladaSa} style={{
          padding: "7px 9px", fontSize: 13, borderRadius: "var(--radius-sm)", border: "1px solid var(--stroke-strong)",
          background: "var(--surface)", color: "var(--text)", fontFamily: "inherit",
        }}>
          {TC_ROLE.map((r) => <option key={r} value={r}>{r === "Admin" ? "Administrátor" : "Technik"}</option>)}
        </select>
        <Btn kind="primary" icon="plus" onClick={pridat} disabled={!vybrany || ukladaSa}>
          {uzExistuje ? "Aktivovať" : "Pridať"}
        </Btn>
      </div>
      {uzExistuje && uzExistuje.aktivny && (
        <div style={{ fontSize: 12, color: "var(--p-vysoka)", marginTop: 8 }}>
          {vybrany.meno} je už aktívny technik — zmeň mu rolu priamo v zozname nižšie.
        </div>
      )}
      {chyba && <div style={{ fontSize: 12.5, color: "var(--red)", marginTop: 8 }}>{chyba}</div>}
    </div>
  );
}

// História zmien — zobrazí sa, len keď je zoznam TECHNICI_LOG založený. Kým nie je, ponúkne
// tlačidlo na jeho vytvorenie cez Graph (viď graph.jsx vytvorZoznamLoguTechnikov) — ak appka
// nemá na to dostatočné oprávnenie, ukáže presnú chybu a špecifikáciu na ručné založenie.
function TcLog({ zaznamy, nacitavaSa, zriadeny, onZriadit }) {
  const [zakladaSa, setZakladaSa] = useState(false);
  const [vysledok, setVysledok] = useState(null); // { ok, text }

  const zriadit = async () => {
    setZakladaSa(true);
    setVysledok(null);
    try {
      const list = await window.HELPDESK_GRAPH.vytvorZoznamLoguTechnikov();
      setVysledok({ ok: true, text: "Zoznam vytvorený (ID " + list.id + "). V tejto session sa doň už zapisuje aj zobrazuje — pošli ale toto ID Claudovi, nech ho natrvalo zapíše do config.jsx (inak sa pri ďalšom nasadení/inom technikovi stratí)." });
      onZriadit(); // vynúti prekreslenie rodiča — logZriadeny sa prepočíta z window.HELPDESK_CONFIG
    } catch (e) {
      setVysledok({
        ok: false,
        text: "Nepodarilo sa vytvoriť automaticky (" + (e.message || e) + "). Založ ručne v SharePointe: nový zoznam „TechniciLog“ so stĺpcami Akcia, TechnikMeno, VykonalMeno, VykonalEmail (všetky Single line of text) a pošli ID zoznamu Claudovi.",
      });
    } finally {
      setZakladaSa(false);
    }
  };

  if (!zriadeny) {
    return (
      <div style={{ padding: 16, background: "var(--surface)", border: "1px dashed var(--stroke-strong)", borderRadius: "var(--radius-lg)" }}>
        <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 6 }}>História zmien</div>
        <div style={{ fontSize: 12.5, color: "var(--text-2)", marginBottom: 10 }}>
          Log zatiaľ nie je zriadený — zmeny sa vykonávajú, len sa nikam nezapisujú.
        </div>
        <Btn onClick={zriadit} disabled={zakladaSa}>{zakladaSa ? "Zakladám…" : "Vytvoriť teraz"}</Btn>
        {vysledok && (
          <div style={{ fontSize: 12.5, marginTop: 10, color: vysledok.ok ? "var(--green)" : "var(--red)" }}>{vysledok.text}</div>
        )}
      </div>
    );
  }

  return (
    <div style={{ padding: 16, background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)" }}>
      <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 10 }}>História zmien</div>
      {nacitavaSa ? (
        <div style={{ fontSize: 12.5, color: "var(--text-3)" }}>Načítavam…</div>
      ) : !zaznamy.length ? (
        <div style={{ fontSize: 12.5, color: "var(--text-3)" }}>Zatiaľ žiadne zmeny.</div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10, maxHeight: 320, overflowY: "auto" }}>
          {zaznamy.map((z) => (
            <div key={z.id} style={{ fontSize: 12.5, borderBottom: "1px solid var(--stroke)", paddingBottom: 8 }}>
              <div><b>{z.akcia}</b>{z.technikMeno ? " — " + z.technikMeno : ""}</div>
              {/* Title (z.detail) je pri jednoduchých akciách (aktivovať/deaktivovať) zámerne
                  rovnaký ako Akcia (zapisDoLoguTechnikov: Title = detail || akcia) — zobraziť
                  ho ešte raz by bolo len opakovanie tej istej informácie. */}
              {z.detail && z.detail !== z.akcia && <div style={{ color: "var(--text-2)" }}>{z.detail}</div>}
              <div style={{ color: "var(--text-3)" }}>{z.vykonalMeno || "?"} · {fmtRelative(z.cas)}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ---------- hlavná obrazovka ---------- */
function TechniciScreen({ technici, ja, reloadData }) {
  const [logZaznamy, setLogZaznamy] = useState([]);
  const [logNacitavaSa, setLogNacitavaSa] = useState(false);
  // `logVerzia` nemá inú úlohu než vynútiť prekreslenie po úspešnom vytvorZoznamLoguTechnikov()
  // (TcLog nižšie) — `logZriadeny` sa číta priamo z window.HELPDESK_CONFIG pri KAŽDOM renderi,
  // nie z Reactového stavu, takže bez tohto bumpu by appka o novovytvorenom zozname v tejto
  // session nevedela, kým by nenastal iný dôvod na render.
  const [logVerzia, setLogVerzia] = useState(0);
  const logZriadeny = !!(window.HELPDESK_CONFIG && window.HELPDESK_CONFIG.LIST_ID.TECHNICI_LOG);

  const nacitajLog = useCallback(() => {
    if (!logZriadeny) return;
    setLogNacitavaSa(true);
    window.HELPDESK_GRAPH.listTechnikovLog()
      .then((items) => setLogZaznamy(items.map((it) => {
        const f = it.fields || {};
        return { id: it.id, akcia: f.Akcia || "", technikMeno: f.TechnikMeno || "", detail: f.Title || "", vykonalMeno: f.VykonalMeno || "", cas: it.createdDateTime ? new Date(it.createdDateTime).getTime() : Date.now() };
      })))
      .catch(() => {})
      .finally(() => setLogNacitavaSa(false));
  }, [logZriadeny]);

  useEffect(() => { nacitajLog(); }, [nacitajLog]);

  // Po každej zmene: best-effort zápis do logu (nikdy neblokuje samotnú zmenu, viď graph.jsx)
  // + obnovenie zdieľaných dát appky (TECHNICI v initialData), nech sa nová rola/aktivita
  // prejaví aj v Komunikácii/Gantte/štatistikách bez potreby ručného refreshu.
  const poZmene = async (technikMeno, akcia, detail) => {
    await window.HELPDESK_GRAPH.zapisDoLoguTechnikov({
      Title: detail || akcia, Akcia: akcia, TechnikMeno: technikMeno, VykonalMeno: ja.meno, VykonalEmail: ja.email,
    });
    nacitajLog();
    await reloadData(true);
  };

  const zoradeni = useMemo(() => [...technici].sort((a, b) => (b.aktivny - a.aktivny) || a.meno.localeCompare(b.meno, "sk")), [technici]);

  return (
    <div style={{ flex: 1, minHeight: 0, overflow: "auto", background: "var(--bg)", padding: 24 }}>
      <div style={{ maxWidth: 900, margin: "0 auto", display: "flex", flexDirection: "column", gap: 20 }}>
        <div>
          <div style={{ fontSize: 18, fontWeight: 700 }}>Správa technikov</div>
          <div style={{ fontSize: 13, color: "var(--text-3)" }}>Kto má prístup do technickej strany a akú rolu.</div>
        </div>

        <TcPridatTechnika technici={technici} jaMeno={ja.meno} jaEmail={ja.email} onPridany={poZmene} />

        <div style={{ background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)", overflow: "hidden" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
            <thead>
              <tr style={{ background: "var(--surface-2)" }}>
                <th style={{ padding: "9px 12px", textAlign: "left", fontSize: 11, fontWeight: 700, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: ".3px" }}>Meno</th>
                <th style={{ padding: "9px 12px", textAlign: "left", fontSize: 11, fontWeight: 700, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: ".3px" }}>Rola</th>
                <th style={{ padding: "9px 12px", width: 140 }} />
              </tr>
            </thead>
            <tbody>
              {zoradeni.map((t) => <TcRiadok key={t.id} t={t} onZmena={poZmene} />)}
            </tbody>
          </table>
        </div>

        <TcLog zaznamy={logZaznamy} nacitavaSa={logNacitavaSa} zriadeny={logZriadeny} onZriadit={() => setLogVerzia((v) => v + 1)} />
      </div>
    </div>
  );
}

window.TechniciScreen = TechniciScreen;
