// SOLCOM Website-Abnahme · Ticket-Ableitung (Jira) — live Anbindung an /api/derive + /api/tickets
(function () {
  const DS = window.AdessoPlaybooksDesignSystem_29634e;
  const { Button, Badge } = DS;

  const PRIO_TONE = { Niedrig: "var(--ink-400)", Mittel: "var(--blue-500)", Hoch: "var(--warning)", Kritisch: "var(--danger)" };

  const QUILL_TOOLBAR = [{ header: [2, 3, false] }, "bold", "italic", { list: "ordered" }, { list: "bullet" }, "clean"];

  // Editor-Chrome & Titel-Input ans Design angepasst
  const SCREEN_CSS = `
    .sc-ticket-card .ql-toolbar.ql-snow {
      border: 1px solid var(--ink-200);
      border-radius: var(--radius-lg) var(--radius-lg) 0 0;
      background: #fff;
      font-family: var(--font-sans);
      padding: 7px 9px;
    }
    .sc-ticket-card .ql-container.ql-snow {
      border: 1px solid var(--ink-200);
      border-top: 0;
      border-radius: 0 0 var(--radius-lg) var(--radius-lg);
      background: #fff;
      font-family: var(--font-sans);
      font-size: 14px;
    }
    .sc-ticket-card .ql-editor {
      min-height: 150px;
      line-height: 1.55;
      color: var(--ink-800);
      font-family: var(--font-sans);
      font-size: 14px;
    }
    .sc-ticket-card .ql-snow .ql-picker,
    .sc-ticket-card .ql-snow .ql-picker-label {
      font-family: var(--font-sans);
      font-size: 13px;
    }
    .sc-ticket-card.sc-ticket-created .ql-toolbar.ql-snow { opacity: .55; pointer-events: none; }
    .sc-ticket-card.sc-ticket-created .ql-container.ql-snow { background: var(--ink-50); }
    .sc-ticket-title {
      width: 100%;
      box-sizing: border-box;
      font-family: var(--font-sans);
      font-size: 17px;
      font-weight: 600;
      color: var(--ink-1000);
      background: #fff;
      border: 1px solid var(--ink-200);
      border-radius: var(--radius-lg);
      padding: 9px 13px;
      outline: none;
      transition: border-color .12s ease;
    }
    .sc-ticket-title:focus { border-color: var(--blue-500); }
    .sc-ticket-title[readonly] { background: var(--ink-50); color: var(--ink-700); }
  `;

  function esc(s) {
    return String(s == null ? "" : s)
      .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
  }

  function attachmentName(a) {
    if (typeof a === "string") return a;
    return (a && (a.name || a.filename)) || "";
  }

  // Initiale Ticket-Beschreibung gemäß SPEC: Kontext / Beobachtung / ggf. Anhänge
  function initialDescriptionHtml(c) {
    let html =
      "<h3>Kontext</h3><p><em>" + esc(c.userStory) + "</em></p>" +
      "<h3>Beobachtung</h3><p>" + esc(c.feedback || "—") + "</p>";
    const atts = (c.attachments || []).map(attachmentName).filter(Boolean);
    if (atts.length) html += "<ul>" + atts.map((a) => "<li>" + esc(a) + "</li>").join("") + "</ul>";
    return html;
  }

  function PrioritySelect({ value, onChange, disabled }) {
    const S = window.SOLCOM;
    const priorities = (S && S.PRIORITIES) || ["Niedrig", "Mittel", "Hoch", "Kritisch"];
    return (
      <div style={{ display: "inline-flex", gap: 6, flexWrap: "wrap" }}>
        {priorities.map((p) => {
          const active = p === value;
          return (
            <button key={p} disabled={disabled} onClick={() => !disabled && onChange(p)}
              style={{
                cursor: disabled ? "default" : "pointer", font: "inherit", fontSize: 12.5, padding: "5px 11px",
                borderRadius: "var(--radius-full)", border: "1px solid",
                borderColor: active ? PRIO_TONE[p] : "var(--ink-200)",
                background: active ? PRIO_TONE[p] : "#fff",
                color: active ? "#fff" : "var(--ink-600)",
                opacity: disabled && !active ? 0.55 : 1,
                transition: "all .12s ease",
              }}>
              {p}
            </button>
          );
        })}
      </div>
    );
  }

  const MONO_LABEL = { fontFamily: "var(--font-mono)", fontSize: 10.5, textTransform: "uppercase", letterSpacing: ".08em", color: "var(--ink-400)" };

  function TicketCard({ area, c, createdInfo, onPrio, onCreated, config, register, unregister }) {
    const [title, setTitle] = React.useState("[" + area.name + "] " + c.title + " — funktioniert nicht");
    const [aiBusy, setAiBusy] = React.useState(false);
    const [createBusy, setCreateBusy] = React.useState(false);
    const [error, setError] = React.useState(null);

    const editorRef = React.useRef(null);
    const quillRef = React.useRef(null);
    const titleRef = React.useRef(title);
    titleRef.current = title;
    const createdRef = React.useRef(createdInfo);
    createdRef.current = createdInfo;
    const prioRef = React.useRef(c.priority);
    prioRef.current = c.priority;

    // Quill einmalig pro Karte instanziieren
    React.useEffect(() => {
      if (!editorRef.current || quillRef.current || !window.Quill) return;
      const q = new window.Quill(editorRef.current, {
        theme: "snow",
        modules: { toolbar: QUILL_TOOLBAR },
      });
      q.clipboard.dangerouslyPasteHTML(initialDescriptionHtml(c));
      if (createdRef.current) q.enable(false);
      quillRef.current = q;
    }, []);

    // Nach Anlage: Editor schreibgeschützt
    React.useEffect(() => {
      if (quillRef.current) quillRef.current.enable(!createdInfo);
    }, [!!createdInfo]);

    const createTicket = async () => {
      if (createdRef.current) return true; // bereits angelegt → kein erneuter Versuch
      setError(null);
      setCreateBusy(true);
      try {
        const res = await fetch("/api/tickets", {
          method: "POST",
          credentials: "same-origin",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            caseId: c.id,
            title: titleRef.current,
            descriptionHtml: quillRef.current ? quillRef.current.getSemanticHTML() : "",
            priority: prioRef.current,
            areaName: area.name,
          }),
        });
        const data = await res.json().catch(() => ({}));
        if (res.status === 201 && data.key) {
          onCreated(c.id, { key: data.key, url: data.url });
          return true;
        }
        setError("Ticket konnte nicht angelegt werden: " + (data.detail || data.error || ("HTTP " + res.status)));
        return false;
      } catch (e) {
        setError("Ticket konnte nicht angelegt werden: " + (e && e.message ? e.message : String(e)));
        return false;
      } finally {
        setCreateBusy(false);
      }
    };

    // Imperative API für die Bulk-Anlage (immer aktueller Editor-Stand)
    const createFnRef = React.useRef(createTicket);
    createFnRef.current = createTicket;
    React.useEffect(() => {
      register(c.id, () => createFnRef.current());
      return () => unregister(c.id);
    }, [c.id]);

    const runDerive = async () => {
      setError(null);
      setAiBusy(true);
      try {
        const res = await fetch("/api/derive", {
          method: "POST",
          credentials: "same-origin",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            title: c.title,
            userStory: c.userStory,
            steps: c.steps || [],
            checkedSteps: c.checkedSteps || [],
            feedback: c.feedback || "",
            areaName: area.name,
          }),
        });
        const data = await res.json().catch(() => ({}));
        if (res.ok && data.title) {
          setTitle(data.title);
          if (quillRef.current && data.descriptionHtml) {
            quillRef.current.clipboard.dangerouslyPasteHTML(data.descriptionHtml);
          }
        } else {
          setError("KI-Vorschlag fehlgeschlagen: " + (data.detail || data.error || ("HTTP " + res.status)));
        }
      } catch (e) {
        setError("KI-Vorschlag fehlgeschlagen: " + (e && e.message ? e.message : String(e)));
      } finally {
        setAiBusy(false);
      }
    };

    const created = !!createdInfo;
    return (
      <div className={"sc-ticket-card" + (created ? " sc-ticket-created" : "")} style={{
        background: "#fff", border: "1px solid var(--ink-200)", borderRadius: "var(--radius-xl)",
        boxShadow: "var(--shadow-1)", overflow: "hidden", opacity: created ? 0.96 : 1,
      }}>
        {/* jira-style header */}
        <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "14px 22px", background: "var(--ink-50)", borderBottom: "1px solid var(--ink-200)", flexWrap: "wrap" }}>
          <i className="ph ph-kanban" style={{ fontSize: 16, color: "var(--blue-500)" }} />
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--ink-600)" }}>{created ? createdInfo.key : "Neues Ticket"}</span>
          <Badge tone="neutral">{area.name}</Badge>
          <span style={{ marginLeft: "auto" }}>
            {created
              ? <Badge tone="done" icon="ph-bold ph-check">in Jira angelegt</Badge>
              : <Badge tone="danger" icon="ph-bold ph-warning">Fehler</Badge>}
          </span>
        </div>

        <div style={{ padding: "20px 22px" }}>
          {/* title (editierbar) */}
          <div style={{ ...MONO_LABEL, marginBottom: 5 }}>Titel</div>
          <input
            className="sc-ticket-title"
            type="text"
            value={title}
            readOnly={created}
            onChange={(e) => setTitle(e.target.value)}
            style={{ margin: "0 0 16px" }}
          />

          {/* description (Quill) */}
          <div style={{ ...MONO_LABEL, marginBottom: 6 }}>Beschreibung (aus Tester-Feedback)</div>
          <div ref={editorRef} />

          {/* footer: priority + actions */}
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, marginTop: 18, flexWrap: "wrap" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <span style={MONO_LABEL}>Priorität</span>
              <PrioritySelect value={c.priority} disabled={created} onChange={(p) => onPrio(area.id, c.id, p)} />
            </div>
            {created ? (
              <a href={createdInfo.url} target="_blank" rel="noreferrer"
                style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: 13.5, color: "var(--success)", fontWeight: 500, textDecoration: "none" }}>
                <i className="ph-bold ph-check-circle" style={{ fontSize: 16 }} /> {createdInfo.key} angelegt
              </a>
            ) : (
              <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
                {config.openaiConfigured ? (
                  <Button variant="ghost" size="sm" icon="ph ph-sparkle" disabled={aiBusy || createBusy} onClick={runDerive} style={{ background: "#fff" }}>
                    {aiBusy ? "Erstelle…" : "KI-Vorschlag"}
                  </Button>
                ) : null}
                <Button variant="primary" size="sm" icon="ph-bold ph-plus" disabled={!config.jiraConfigured || createBusy || aiBusy} onClick={createTicket}>
                  {createBusy ? "Lege an…" : "In Jira-Ticket umwandeln"}
                </Button>
              </div>
            )}
          </div>

          {/* inline error below footer */}
          {error ? (
            <div style={{ display: "flex", alignItems: "flex-start", gap: 7, marginTop: 12, fontSize: 13, lineHeight: 1.45, color: "var(--danger)" }}>
              <i className="ph-bold ph-warning-circle" style={{ fontSize: 15, marginTop: 1 }} />
              <span>{error}</span>
            </div>
          ) : null}
        </div>
      </div>
    );
  }

  function TicketsScreen({ onBack, created, onPrio, onCreated, config }) {
    const S = window.SOLCOM;
    const cfg = config || {};
    const createdMap = created || {};

    // alle als fehlerhaft markierten Testfälle, bereichsübergreifend
    const failing = [];
    ((S && S.areas) || []).forEach((a) => a.cases.forEach((c) => { if (c.works === false) failing.push({ area: a, c }); }));
    const openCount = failing.filter((f) => !createdMap[f.c.id]).length;
    const { isMobile } = window.SC_useViewport();

    // Registry der Karten-Anlege-Funktionen für die Bulk-Anlage
    const cardApis = React.useRef({});
    const register = React.useCallback((id, fn) => { cardApis.current[id] = fn; }, []);
    const unregister = React.useCallback((id) => { delete cardApis.current[id]; }, []);

    const [bulk, setBulk] = React.useState(null); // {current, total} während der Bulk-Anlage
    const [bulkErrors, setBulkErrors] = React.useState(0);

    const createAll = async () => {
      const open = failing.filter((f) => !createdMap[f.c.id]);
      if (!open.length || bulk) return;
      setBulkErrors(0);
      let errs = 0;
      for (let i = 0; i < open.length; i++) {
        setBulk({ current: i + 1, total: open.length });
        const fn = cardApis.current[open[i].c.id];
        if (fn) {
          const ok = await fn(); // sequenziell; bei Einzelfehler weitermachen
          if (!ok) errs++;
        }
      }
      setBulk(null);
      setBulkErrors(errs);
    };

    return (
      <div style={{ background: "var(--ink-50)", minHeight: 560 }}>
        <style>{SCREEN_CSS}</style>
        <div style={{ maxWidth: 900, margin: "0 auto", padding: isMobile ? "0 18px 56px" : "0 40px 64px" }}>
          <div style={{ paddingTop: 28 }}>
            <Button variant="ghost" size="sm" icon="ph-bold ph-arrow-left" onClick={onBack} style={{ background: "#fff" }}>Zum Dashboard</Button>
          </div>

          <div style={{ padding: "22px 0 26px" }}>
            <h1 style={{ fontFamily: "var(--font-cond)", fontSize: isMobile ? 30 : 42, fontWeight: 500, letterSpacing: "-.015em", lineHeight: 1.04, margin: 0, color: "var(--ink-1000)" }}>Ticket-Ableitung</h1>
            <p style={{ margin: "12px 0 0", fontSize: 16, color: "var(--ink-600)", maxWidth: "62ch" }}>
              Alle als <b style={{ color: "var(--danger)" }}>fehlerhaft</b> markierten Testfälle. Prüfen Sie Titel, Beschreibung und Priorität — und legen Sie sie einzeln oder gesammelt als Jira-Tickets an.
            </p>
          </div>

          {failing.length === 0 ? (
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 14, padding: "64px 24px", background: "#fff", border: "1px dashed var(--ink-300)", borderRadius: "var(--radius-xl)", textAlign: "center" }}>
              <i className="ph-duotone ph-check-circle" style={{ fontSize: 44, color: "var(--success)" }} />
              <div style={{ fontFamily: "var(--font-cond)", fontSize: 24, fontWeight: 500, color: "var(--ink-900)" }}>Keine Fehler markiert</div>
              <p style={{ margin: 0, fontSize: 14.5, color: "var(--ink-600)", maxWidth: "44ch" }}>Sobald ein Testfall als „Funktioniert nicht" bewertet wird, erscheint er hier zur Ticket-Ableitung.</p>
            </div>
          ) : (
            <React.Fragment>
              {/* hint banner when Jira is not configured */}
              {!cfg.jiraConfigured ? (
                <div style={{ display: "flex", alignItems: "flex-start", gap: 10, padding: "14px 18px", background: "#fff", border: "1px solid var(--ink-200)", borderRadius: "var(--radius-lg)", marginBottom: 18, fontSize: 14, lineHeight: 1.5, color: "var(--ink-700)" }}>
                  <i className="ph ph-info" style={{ fontSize: 18, color: "var(--ink-500)", marginTop: 1 }} />
                  <span>Jira ist nicht konfiguriert — <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5 }}>JIRA_EMAIL</span> und <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5 }}>JIRA_API_TOKEN</span> in der .env hinterlegen.</span>
                </div>
              ) : null}

              {/* bulk bar */}
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, padding: "16px 22px", background: "#fff", border: "1px solid var(--ink-200)", borderRadius: "var(--radius-xl)", marginBottom: 18, flexWrap: "wrap" }}>
                <span style={{ fontSize: 14.5, color: "var(--ink-700)" }}>
                  <b style={{ color: "var(--ink-1000)" }}>{failing.length}</b> Fehler · <b style={{ color: "var(--ink-1000)" }}>{openCount}</b> noch nicht angelegt
                </span>
                <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
                  <a href={cfg.jiraBoardUrl} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
                    <Button variant="ghost" icon="ph ph-arrow-square-out" style={{ background: "#fff" }}>Board öffnen</Button>
                  </a>
                  <Button variant="primary" icon="ph-bold ph-stack-plus" disabled={openCount === 0 || !cfg.jiraConfigured || !!bulk} onClick={createAll}>
                    {bulk ? "Lege an… " + bulk.current + "/" + bulk.total : "Alle als Jira-Tickets anlegen"}
                  </Button>
                </div>
                {bulkErrors > 0 ? (
                  <span style={{ flexBasis: "100%", display: "flex", alignItems: "center", gap: 7, fontSize: 13, color: "var(--danger)" }}>
                    <i className="ph-bold ph-warning-circle" style={{ fontSize: 15 }} />
                    {bulkErrors} {bulkErrors === 1 ? "Ticket konnte" : "Tickets konnten"} nicht angelegt werden — Details an den jeweiligen Karten.
                  </span>
                ) : null}
              </div>

              <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
                {failing.map(({ area, c }) => (
                  <TicketCard
                    key={c.id} area={area} c={c}
                    createdInfo={createdMap[c.id] || null}
                    onPrio={onPrio}
                    onCreated={onCreated}
                    config={cfg}
                    register={register}
                    unregister={unregister}
                  />
                ))}
              </div>
            </React.Fragment>
          )}
        </div>
      </div>
    );
  }

  window.SC_TicketsScreen = TicketsScreen;
})();
