/* vazba.jsx — "Pripomienky": prehľad spätnej väzby, ktorú zamestnanci posielajú štvorčekom
   v pravom dolnom rohu portálu (SpatnaVazbaTlacidlo v ui.jsx → POST /api/portal/spatna-vazba
   → SharePoint zoznam SpatnaVazba).

   Prečo vlastná obrazovka a nie tikety: pripomienky sa majú len ZBIERAŤ a po čase vyhodnotiť
   (rozhodnutie Jakuba, 2026-09-21). Ako tikety by sa miešali medzi skutočnú prácu, rátali sa
   do štatistík a po 7 dňoch by dokonca začali eskalovať. Preto je táto obrazovka zámerne LEN
   NA ČÍTANIE — nič sa odtiaľto nepriraďuje, nezatvára ani nemaže. Jediná "akcia" je export do
   CSV, teda presne to vyhodnotenie, kvôli ktorému sa pripomienky zbierajú.

   Zoznam sa načítava až po otvorení obrazovky (nie pri štarte appky ako tikety/technici) —
   je to príležitostný prehľad, nie niečo, čo treba mať pri každom prihlásení. */

// Hodnoty stĺpca Odkial zodpovedajú pohľadom portálu (portal.jsx: home | novy | potvrdenie |
// detail). Pri vyhodnocovaní je rozdiel, či ľudia narážajú na niečo hneď na domovskej
// obrazovke alebo až vo formulári novej požiadavky.
const VAZBA_ODKIAL = {
  home: "Domov",
  novy: "Nová požiadavka",
  potvrdenie: "Po odoslaní",
  detail: "Detail požiadavky",
  technik: "Technik (z helpdesku)",
};
// Neznámy kód sa zobrazí tak, ako prišiel — keď v portáli pribudne nový pohľad a zabudne sa
// dopísať sem, nech je to vidno, nie aby sa schoval pod "Neuvedené".
function vazbaOdkialLudsky(kod) {
  return VAZBA_ODKIAL[kod] || (kod ? kod : "Neuvedené");
}

function mapVazba(it) {
  const f = it.fields || {};
  return {
    id: it.id,
    // Title je len prvý riadok textu (tak ho zapisuje Worker, nech je v SharePointe vidno,
    // o čo ide) — zobrazuje sa celý Text, Title je záloha pre staršie/ručne pridané položky.
    text: f.Text || f.Title || "",
    autor: f.Autor || "",
    email: f.AutorEmail || "",
    odkial: f.Odkial || "",
    cas: it.createdDateTime ? new Date(it.createdDateTime).getTime() : 0,
  };
}

/* ---------- export ---------- */
// Bodkočiarka ako oddeľovač a BOM na začiatku — slovenský Excel inak rozhádže stĺpce aj
// diakritiku. Úvodzovky v texte sa zdvojujú (CSV escapovanie), inak by pripomienka s
// úvodzovkami rozbila riadok.
function vazbaDoCsv(polozky) {
  const bunka = (h) => '"' + String(h == null ? "" : h).replace(/"/g, '""') + '"';
  const riadky = [["Dátum", "Autor", "E-mail", "Odkiaľ", "Pripomienka"].map(bunka).join(";")];
  for (const p of polozky) {
    riadky.push([p.cas ? fmtDateTime(p.cas) : "", p.autor, p.email, vazbaOdkialLudsky(p.odkial), p.text].map(bunka).join(";"));
  }
  return "﻿" + riadky.join("\r\n");
}

function stiahniCsv(polozky) {
  const blob = new Blob([vazbaDoCsv(polozky)], { type: "text/csv;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "pripomienky-" + new Date().toISOString().slice(0, 10) + ".csv";
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  // Bez revoke by blob držal pamäť do konca života stránky; timeout preto, lebo Chrome
  // sťahovanie naštartuje až po skončení tohto tiku.
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

/* ---------- jedna pripomienka ---------- */
function VazbaKarta({ p }) {
  return (
    <div style={{
      background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)",
      padding: 14, display: "flex", gap: 12,
    }}>
      <Avatar meno={p.autor || "?"} size={34} photoKey={p.email} />
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap", marginBottom: 5 }}>
          <span style={{ fontSize: 13.5, fontWeight: 700 }}>{p.autor || "Neznámy odosielateľ"}</span>
          {p.email && <span style={{ fontSize: 11.5, color: "var(--text-3)" }}>{p.email}</span>}
          <span style={{ marginLeft: "auto", fontSize: 11.5, color: "var(--text-3)", whiteSpace: "nowrap" }}
            title={p.cas ? fmtDateTime(p.cas) : ""}>
            {p.cas ? fmtRelative(p.cas) : "-"}
          </span>
        </div>
        {/* pre-wrap: pripomienky chodia z textarea, viacriadkové sa musia zobraziť tak,
            ako ich človek napísal. overflowWrap kvôli dlhým slovám/URL bez medzier. */}
        <div style={{ fontSize: 13.5, lineHeight: 1.55, whiteSpace: "pre-wrap", overflowWrap: "anywhere" }}>{p.text}</div>
        <div style={{ marginTop: 8 }}>
          <span style={{
            display: "inline-block", padding: "2px 8px", borderRadius: 999, fontSize: 11, fontWeight: 600,
            background: "var(--surface-3)", color: "var(--text-2)",
          }}>{vazbaOdkialLudsky(p.odkial)}</span>
        </div>
      </div>
    </div>
  );
}

/* ---------- prehľadové číslo ---------- */
function VazbaCislo({ label, hodnota }) {
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)", padding: "12px 16px", minWidth: 120 }}>
      <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-.02em" }}>{hodnota}</div>
      <div style={{ fontSize: 11.5, color: "var(--text-3)", fontWeight: 600 }}>{label}</div>
    </div>
  );
}

/* ---------- formulár: nová pripomienka od technika ----------
   Technici nemajú v pracovnej časti štvorček spätnej väzby ako zamestnanci v portáli, preto sa
   pripomienka k systému dá poslať odtiaľto (Jakub, 2026-10-12). Zapisuje sa do rovnakého
   zoznamu SpatnaVazba s Odkial = "technik". */
function NovaVazbaFormular({ ja, onOdoslane, onZrusit }) {
  const [text, setText] = useState("");
  const [stav, setStav] = useState(""); // "" | "odosielam"
  const [chyba, setChyba] = useState("");
  const taRef = useRef(null);
  useEffect(() => { if (taRef.current) taRef.current.focus(); }, []);
  const odoslat = async () => {
    const v = text.trim();
    if (!v) { setChyba("Napíšte prosím, čo vám nesedí alebo čo by sa dalo zlepšiť."); return; }
    if (v.length > 4000) { setChyba("Pripomienka je príliš dlhá (najviac 4000 znakov)."); return; }
    if (stav === "odosielam") return;
    setStav("odosielam"); setChyba("");
    try {
      await window.HELPDESK_GRAPH.zapisSpatnuVazbu({ text: v, autor: ja && ja.meno, email: ja && ja.email });
      setText("");
      onOdoslane();
    } catch (e) {
      setStav("");
      setChyba("Odoslanie zlyhalo: " + (e.message || e) + " Ak sa to opakuje, skontrolujte oprávnenie na zoznam SpatnaVazba.");
    }
  };
  return (
    <div>
      <textarea ref={taRef} value={text} onChange={(e) => { setText(e.target.value); setChyba(""); }} rows={6} maxLength={4000}
        onKeyDown={(e) => { if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) odoslat(); }}
        placeholder="Čo vám v helpdesku nevyhovuje, čo chýba alebo čo by sa dalo zlepšiť? (Ctrl+Enter odošle)"
        style={{
          width: "100%", boxSizing: "border-box", padding: "10px 12px", fontSize: 13.5, lineHeight: 1.55, borderRadius: "var(--radius)",
          border: "1px solid " + (chyba ? "var(--red)" : "var(--stroke-strong)"), background: "var(--surface-2)", color: "var(--text)",
          fontFamily: "inherit", resize: "vertical", minHeight: 120, outline: "none",
        }} />
      {chyba && (
        <div style={{ display: "flex", gap: 6, alignItems: "flex-start", marginTop: 8, fontSize: 12.5, color: "var(--red)" }}>
          <Icon name="warning" size={14} style={{ flexShrink: 0, marginTop: 1 }} /> {chyba}
        </div>
      )}
      <div style={{ display: "flex", gap: 8, marginTop: 12, alignItems: "center" }}>
        <Btn kind="primary" icon="send" onClick={odoslat} disabled={stav === "odosielam"}>{stav === "odosielam" ? "Odosielam..." : "Odoslať pripomienku"}</Btn>
        {onZrusit && <Btn kind="subtle" onClick={onZrusit} disabled={stav === "odosielam"}>Zrušiť</Btn>}
        <span style={{ marginLeft: "auto", fontSize: 11.5, color: "var(--text-3)" }}>{text.length} / 4000</span>
      </div>
    </div>
  );
}

// Okno nad obrazovkou (pre admina, ktorý má pod tým zoznam pripomienok).
function NovaVazbaOkno({ ja, onZavriet, onOdoslane }) {
  return (
    <div onMouseDown={(e) => { if (e.target === e.currentTarget) onZavriet(); }} style={{
      position: "fixed", inset: 0, zIndex: 60, background: "rgba(0,0,0,.35)", overflowY: "auto",
      display: "flex", justifyContent: "center", alignItems: "flex-start", padding: "8vh 16px", boxSizing: "border-box",
    }}>
      <div role="dialog" aria-label="Nová pripomienka" onKeyDown={(e) => { if (e.key === "Escape") onZavriet(); }} style={{
        width: 560, maxWidth: "100%", background: "var(--surface)", borderRadius: "var(--radius)", border: "1px solid var(--stroke)",
        boxShadow: "var(--shadow-lg)", padding: 18, animation: "hd-pop .12s ease",
      }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
          <span style={{ fontSize: 15, fontWeight: 700 }}>Nová pripomienka</span>
          <IconBtn name="close" title="Zavrieť" size={16} onClick={onZavriet} />
        </div>
        <NovaVazbaFormular ja={ja} onOdoslane={onOdoslane} onZrusit={onZavriet} />
      </div>
    </div>
  );
}

// Technik (nie admin) pripomienky nečíta: sú to podklady na vyhodnotenie systému od zamestnancov,
// nie pracovná fronta. Vidí len tento formulár.
function VazbaLenOdoslat({ ja, flash }) {
  const [odoslane, setOdoslane] = useState(false);
  return (
    <div style={{ flex: 1, minHeight: 0, overflow: "auto", background: "var(--bg)", padding: 24 }}>
      <div style={{ maxWidth: 620, margin: "0 auto", display: "flex", flexDirection: "column", gap: 16 }}>
        <div>
          <div style={{ fontSize: 18, fontWeight: 700 }}>Nová pripomienka k helpdesku</div>
          <div style={{ fontSize: 13, color: "var(--text-3)", marginTop: 2 }}>Čo vám v systéme chýba, prekáža alebo by sa dalo zlepšiť. Pripomienky sa zbierajú a administrátor ich vyhodnocuje, nie sú to tikety.</div>
        </div>
        <div style={{ background: "var(--surface)", border: "1px solid var(--stroke)", borderRadius: "var(--radius-lg)", padding: 16 }}>
          {odoslane ? (
            <div style={{ textAlign: "center", padding: "18px 8px" }}>
              <div style={{ color: "var(--green)", marginBottom: 8 }}><Icon name="checkCircle" size={30} /></div>
              <div style={{ fontWeight: 700, marginBottom: 4 }}>Ďakujeme, pripomienka je odoslaná</div>
              <div style={{ fontSize: 12.5, color: "var(--text-2)", marginBottom: 14 }}>Ak máte ďalší nápad, pokojne pošlite aj ten.</div>
              <Btn onClick={() => setOdoslane(false)}>Napísať ďalšiu</Btn>
            </div>
          ) : (
            <NovaVazbaFormular ja={ja} onOdoslane={() => { setOdoslane(true); if (flash) flash("Pripomienka odoslaná", "success"); }} />
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- hlavná obrazovka ---------- */
function SpatnaVazbaScreen({ jeAdmin, ja, flash }) {
  if (!jeAdmin) return <VazbaLenOdoslat ja={ja} flash={flash} />;
  return <VazbaPrehlad ja={ja} flash={flash} />;
}

function VazbaPrehlad({ ja, flash }) {
  const [novaOtvorena, setNovaOtvorena] = useState(false);
  const [polozky, setPolozky] = useState([]);
  const [nacitavaSa, setNacitavaSa] = useState(true);
  const [chyba, setChyba] = useState("");
  const [hladanie, setHladanie] = useState("");
  const [odkial, setOdkial] = useState("vsetky");

  const nacitaj = useCallback(() => {
    setNacitavaSa(true);
    setChyba("");
    window.HELPDESK_GRAPH.listSpatnaVazba()
      .then((items) => setPolozky(items.map(mapVazba).sort((a, b) => b.cas - a.cas)))
      .catch((e) => setChyba(e.message || String(e)))
      .finally(() => setNacitavaSa(false));
  }, []);

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

  // Ponuka filtra sa skladá z toho, čo v dátach naozaj je — nie z VAZBA_ODKIAL. Filter na
  // pohľad, z ktorého zatiaľ nikto nič neposlal, by len ukazoval prázdno.
  const odkialMoznosti = useMemo(() => {
    const zoznam = [];
    for (const p of polozky) if (!zoznam.includes(p.odkial)) zoznam.push(p.odkial);
    return zoznam.sort((a, b) => vazbaOdkialLudsky(a).localeCompare(vazbaOdkialLudsky(b), "sk"));
  }, [polozky]);

  const filtrovane = useMemo(() => {
    const q = hladanie.trim().toLowerCase();
    return polozky.filter((p) => {
      if (odkial !== "vsetky" && p.odkial !== odkial) return false;
      if (!q) return true;
      return (p.text + " " + p.autor + " " + p.email).toLowerCase().includes(q);
    });
  }, [polozky, hladanie, odkial]);

  const zaTyzden = useMemo(() => {
    const hranica = Date.now() - 7 * 24 * 3600 * 1000;
    return polozky.filter((p) => p.cas >= hranica).length;
  }, [polozky]);

  const vstupStyl = {
    padding: "8px 11px", fontSize: 13, borderRadius: "var(--radius-sm)", border: "1px solid var(--stroke-strong)",
    background: "var(--surface)", color: "var(--text)", fontFamily: "inherit", outline: "none",
  };

  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: 18 }}>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 12, flexWrap: "wrap" }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 18, fontWeight: 700 }}>Pripomienky k helpdesku</div>
            <div style={{ fontSize: 13, color: "var(--text-3)" }}>Čo zamestnancom v systéme chýba alebo prekáža. Nie sú to tikety, len sa zbierajú na vyhodnotenie.</div>
          </div>
          <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
            <Btn kind="primary" icon="plus" onClick={() => setNovaOtvorena(true)}>Nová pripomienka</Btn>
            <Btn icon="refresh" onClick={nacitaj} disabled={nacitavaSa}>{nacitavaSa ? "Načítavam..." : "Obnoviť"}</Btn>
            <Btn icon="file" onClick={() => stiahniCsv(filtrovane)} disabled={!filtrovane.length}>Stiahnuť CSV</Btn>
          </div>
        </div>

        {chyba ? (
          <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, color: "var(--red)" }}>Pripomienky sa nepodarilo načítať</div>
            <div style={{ fontSize: 12.5, color: "var(--text-2)", lineHeight: 1.5 }}>{chyba}</div>
          </div>
        ) : (
          <>
            <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
              <VazbaCislo label="Spolu" hodnota={polozky.length} />
              <VazbaCislo label="Za posledných 7 dní" hodnota={zaTyzden} />
              <VazbaCislo label="Posledná" hodnota={polozky.length ? fmtRelative(polozky[0].cas) : "-"} />
            </div>

            <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
              <input value={hladanie} onChange={(e) => setHladanie(e.target.value)} placeholder="Hľadať v pripomienkach..."
                style={{ ...vstupStyl, flex: "1 1 220px", minWidth: 0 }} />
              <select value={odkial} onChange={(e) => setOdkial(e.target.value)} style={vstupStyl}>
                <option value="vsetky">Odkiaľ: všetky</option>
                {odkialMoznosti.map((k) => <option key={k} value={k}>{vazbaOdkialLudsky(k)}</option>)}
              </select>
            </div>

            {nacitavaSa && !polozky.length ? (
              <div style={{ fontSize: 13, color: "var(--text-3)" }}>Načítavam...</div>
            ) : !polozky.length ? (
              <div style={{ padding: 20, background: "var(--surface)", border: "1px dashed var(--stroke-strong)", borderRadius: "var(--radius-lg)", textAlign: "center" }}>
                <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 4 }}>Zatiaľ žiadne pripomienky</div>
                <div style={{ fontSize: 12.5, color: "var(--text-2)" }}>Objavia sa tu, keď niekto použije štvorček spätnej väzby v portáli.</div>
              </div>
            ) : !filtrovane.length ? (
              <div style={{ fontSize: 13, color: "var(--text-3)" }}>Filtru nezodpovedá žiadna pripomienka.</div>
            ) : (
              <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                {filtrovane.map((p) => <VazbaKarta key={p.id} p={p} />)}
              </div>
            )}
          </>
        )}
      </div>
      {novaOtvorena && (
        <NovaVazbaOkno ja={ja} onZavriet={() => setNovaOtvorena(false)}
          onOdoslane={() => { setNovaOtvorena(false); if (flash) flash("Pripomienka odoslaná", "success"); nacitaj(); }} />
      )}
    </div>
  );
}

window.SpatnaVazbaScreen = SpatnaVazbaScreen;
