// Knowledge base — operator playbooks the support agent reasons with.
//
// Drop a doc here (paste, or a .md/.txt file) and the agent retrieves it as RAG
// at intake and severity-grading time, and when suggesting an assignee. This is
// INTERNAL guidance ("how we grade severity", "who owns what") — never shown to
// customers, distinct from the customer-facing help KB (Confluence/seed).
const { useState: useStateKB, useEffect: useEffectKB, useRef: useRefKB } = React;

// Starter templates for the two canonical playbooks, so an empty KB isn't a
// blank page. They match the examples the team asked for.
const TEMPLATES = [
  {
    label: "Severity rubric",
    title: "How to grade severity",
    body: `Grade severity as impact × urgency. Team-specific rules that override the defaults:

- Anything touching Deal Rooms during an active deal is at least SEV2 — that's where revenue lives.
- Forecast wrong/missing numbers before month-end or a QBR → SEV1, even for one rep.
- Addy (AI copilot) giving a wrong answer is SEV3 unless it's fabricating data, then SEV2.
- A cosmetic issue is SEV4 even if the customer is angry about it.
- "The whole team" or "nobody can" → never below SEV2.`,
    tags: ["severity", "grading", "priority"],
  },
  {
    label: "Assignment routing",
    title: "Who to assign the ticket to",
    body: `Route bugs to the owner by area:

- Deal Rooms, Openings / Outbound → Amine
- Forecast, Notifications, Slack integration → Houssem
- Addy (AI copilot), anything ML → Dhia
- Settings, auth, billing → Aymen
- SEV1 anything → assign to whoever owns the area AND flag Ridha.
- If the area is unclear, leave unassigned and note why.`,
    tags: ["assignment", "routing", "owner"],
  },
];

function DocForm({ initial, onSave, onCancel, busy }) {
  const [title, setTitle] = useStateKB(initial ? initial.title : "");
  const [body, setBody] = useStateKB(initial ? initial.body : "");
  const [tags, setTags] = useStateKB(initial ? (initial.tags || []).join(", ") : "");
  const fileRef = useRefKB(null);

  function onFile(e) {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    const r = new FileReader();
    r.onload = () => {
      setBody(String(r.result || ""));
      if (!title) setTitle(f.name.replace(/\.(md|txt|markdown)$/i, ""));
    };
    r.readAsText(f);
  }

  return (
    <div className="kb-form card">
      <div className="be-field">
        <span className="be-label">Title</span>
        <input value={title} onChange={(e) => setTitle(e.target.value)} placeholder="e.g. How to grade severity" disabled={busy} />
      </div>
      <div className="be-field">
        <span className="be-label">Content <em>plain text or markdown — the agent reads this verbatim</em></span>
        <textarea rows={10} value={body} onChange={(e) => setBody(e.target.value)}
          placeholder={"Drop the guidance here.\n\n- rule one\n- rule two"} disabled={busy} />
      </div>
      <div className="be-field">
        <span className="be-label">Tags <em>comma-separated · help the agent find this</em></span>
        <input value={tags} onChange={(e) => setTags(e.target.value)} placeholder="severity, assignment" disabled={busy} />
      </div>
      <div className="kb-form-foot">
        <input ref={fileRef} type="file" accept=".md,.txt,.markdown,text/*" style={{ display: "none" }} onChange={onFile} />
        <button className="btn btn-ghost btn-sm" onClick={() => fileRef.current && fileRef.current.click()} disabled={busy}>
          Drop a .md / .txt file
        </button>
        <div className="kb-form-foot-right">
          {onCancel && <button className="btn btn-ghost btn-sm" onClick={onCancel} disabled={busy}>Cancel</button>}
          <button className="btn btn-primary btn-sm"
            onClick={() => onSave({ title: title.trim(), body: body.trim(), tags })}
            disabled={busy || !title.trim() || !body.trim()}>
            {busy ? "Saving…" : "Save doc"}
          </button>
        </div>
      </div>
    </div>
  );
}

function DocRow({ doc, onEdit, onDelete, busy }) {
  const [open, setOpen] = useStateKB(false);
  return (
    <div className={"pq-row kb-row" + (open ? " is-open" : "")}>
      <div className="pq-main">
        <button className="pq-title" onClick={() => setOpen((v) => !v)} aria-expanded={open}>
          <span className="pq-text">{doc.title}</span>
          <span className={"ticket-chev" + (open ? " is-open" : "")} aria-hidden="true">⌄</span>
        </button>
        <div className="pq-meta">
          {(doc.tags || []).map((t) => <span key={t} className="kb-tag">{t}</span>)}
          <span>· updated {window.fmtAgo ? window.fmtAgo(doc.updatedAt) : ""}</span>
        </div>
        {open && <pre className="kb-body">{doc.body}</pre>}
      </div>
      <div className="pq-controls kb-controls">
        <button className="btn btn-ghost btn-sm" onClick={() => onEdit(doc)} disabled={busy}>Edit</button>
        <button className="btn btn-ghost btn-sm" onClick={() => onDelete(doc)} disabled={busy}>Delete</button>
      </div>
    </div>
  );
}

function Knowledge() {
  const [state, setState] = useStateKB({ loading: true, live: false, docs: [] });
  const [adding, setAdding] = useStateKB(false);
  const [editing, setEditing] = useStateKB(null);
  const [busy, setBusy] = useStateKB(false);
  const [dragover, setDragover] = useStateKB(false);
  const topFileRef = useRefKB(null);

  async function load() {
    const r = await window.NS.admin.kb.list();
    setState({ loading: false, live: !!r.live, docs: r.docs || [], error: r.error });
  }
  useEffectKB(() => { load(); }, []);

  // Upload one or more .md/.txt files straight into the KB — each file becomes a
  // doc (filename → title, contents → body). This is the fast path; the form is
  // for typing/editing. Reads happen in the browser (FileReader); nothing is
  // uploaded anywhere but our own KB.
  async function ingestFiles(fileList) {
    const files = [...(fileList || [])].filter((f) => /\.(md|txt|markdown)$/i.test(f.name) || f.type.startsWith("text"));
    if (!files.length) { if (window.fireToast) window.fireToast("Only .md / .txt files"); return; }
    setBusy(true);
    let n = 0;
    for (const f of files) {
      const body = await f.text().catch(() => "");
      if (!body.trim()) continue;
      const res = await window.NS.admin.kb.add({
        title: f.name.replace(/\.(md|txt|markdown)$/i, ""), body, tags: [],
      });
      if (res.ok) n++;
    }
    setBusy(false);
    if (window.fireToast) window.fireToast(n === 1 ? "1 doc added" : n + " docs added");
    load();
  }

  async function save(doc) {
    setBusy(true);
    const res = editing ? await window.NS.admin.kb.update(editing.id, doc) : await window.NS.admin.kb.add(doc);
    setBusy(false);
    if (!res.ok) { if (window.fireToast) window.fireToast("Couldn't save: " + (res.error || "error")); return; }
    setAdding(false); setEditing(null);
    if (window.fireToast) window.fireToast(editing ? "Doc updated" : "Doc added — the agent will use it");
    load();
  }
  async function remove(doc) {
    setBusy(true);
    const res = await window.NS.admin.kb.remove(doc.id);
    setBusy(false);
    if (res.ok && window.fireToast) window.fireToast("Doc removed");
    load();
  }
  async function useTemplate(t) {
    setBusy(true);
    await window.NS.admin.kb.add({ title: t.title, body: t.body, tags: t.tags });
    setBusy(false);
    if (window.fireToast) window.fireToast("Added: " + t.title);
    load();
  }

  if (state.loading) return <div className="pq-empty">Loading…</div>;

  return (
    <div>
      <div className="page-head">
        <div className="eyebrow">Knowledge</div>
        <h1 className="page-title">Agent playbooks</h1>
        <p className="page-sub">
          Internal guidance the support agent follows when it grades severity, triages, and suggests who to assign a
          ticket to. Drop a doc and the agent picks it up on the next report — <strong>never shown to customers</strong>.
        </p>
      </div>

      {!state.live && state.error === "no_store" && (
        <div className="admin-note">
          <strong>No datastore.</strong> Playbooks live in the KV store — set{" "}
          <code>UPSTASH_REDIS_REST_URL</code> + <code>UPSTASH_REDIS_REST_TOKEN</code> to use them.
        </div>
      )}
      {!state.live && state.error && state.error !== "no_store" && (
        <div className="admin-note">
          <strong>Couldn't load playbooks{state.error === "admin_required" ? " — your session expired" : ""}.</strong>{" "}
          {state.error === "admin_required" ? "Sign out and back in." : `(${state.error})`}
        </div>
      )}

      {state.live && (
        <React.Fragment>
          {!adding && !editing && (
            <div className="kb-actions">
              <button className="btn btn-primary btn-sm" onClick={() => setAdding(true)}>+ Write a playbook</button>
              <input ref={topFileRef} type="file" accept=".md,.txt,.markdown,text/*" multiple
                style={{ display: "none" }} onChange={(e) => ingestFiles(e.target.files)} />
              <button className="btn btn-ghost btn-sm" onClick={() => topFileRef.current && topFileRef.current.click()} disabled={busy}>
                ⬆ Upload .md / .txt files
              </button>
            </div>
          )}

          {!adding && !editing && (
            <div className={"kb-drop" + (dragover ? " is-over" : "")}
              onDragOver={(e) => { e.preventDefault(); setDragover(true); }}
              onDragLeave={() => setDragover(false)}
              onDrop={(e) => { e.preventDefault(); setDragover(false); ingestFiles(e.dataTransfer.files); }}>
              {busy ? "Reading files…" : "Drop .md / .txt files here to add them as playbooks"}
            </div>
          )}
          {(adding || editing) && (
            <DocForm initial={editing} busy={busy}
              onSave={save} onCancel={() => { setAdding(false); setEditing(null); }} />
          )}

          {!state.docs.length && !adding && (
            <div className="kb-empty">
              <p className="rs-sub">No playbooks yet. Start from a template:</p>
              <div className="kb-templates">
                {TEMPLATES.map((t) => (
                  <button key={t.label} className="kb-template" onClick={() => useTemplate(t)} disabled={busy}>
                    <strong>{t.label}</strong>
                    <span>{t.title}</span>
                  </button>
                ))}
              </div>
            </div>
          )}

          {!!state.docs.length && (
            <div className="pq">
              {state.docs.map((d) => (
                <DocRow key={d.id} doc={d} busy={busy}
                  onEdit={(doc) => { setEditing(doc); setAdding(false); }} onDelete={remove} />
              ))}
            </div>
          )}
        </React.Fragment>
      )}
    </div>
  );
}

window.Knowledge = Knowledge;
