// Atlas · Step 2 — Scope review with themed question groups

// ── Module-scope utilities (must be outside component to avoid remount on every render) ──
function autoResize(el) {
  if (!el) return;
  el.style.height = "auto";
  el.style.height = el.scrollHeight + "px";
}

const _scopeRowRef = (el) => { if (el) autoResize(el); };

function ScopeRow({ prefix, value, onChange, onDelete, placeholder }) {
  return (
    <div className="scope-row">
      {prefix && <span className="scope-row-num">{prefix}</span>}
      <textarea
        ref={_scopeRowRef}
        className="scope-input"
        rows={1}
        value={value}
        placeholder={placeholder || ""}
        onChange={e => { onChange(e.target.value); autoResize(e.target); }}
        onInput={e => autoResize(e.target)}
      />
      <button className="scope-row-del" onClick={onDelete} title="Remove">×</button>
    </div>
  );
}

function ThemeLabel({ value, onChange, onDelete, showDelete }) {
  const [editing, setEditing] = React.useState(false);
  return (
    <div className="scope-theme-header">
      {editing ? (
        <input
          className="scope-theme-input"
          autoFocus
          value={value}
          onChange={e => onChange(e.target.value)}
          onBlur={() => setEditing(false)}
          onKeyDown={e => e.key === "Enter" && setEditing(false)}
        />
      ) : (
        <span className="scope-theme-label" onClick={() => setEditing(true)} title="Click to rename">
          {value || "Unnamed Theme"}
        </span>
      )}
      {showDelete && (
        <button className="scope-theme-del" onClick={onDelete} title="Remove theme and all its questions">×</button>
      )}
    </div>
  );
}

function StepScope({ state, reportId, parsedScope, goBack, goNext, goForward, loading, error, readOnly }) {
  const title     = parsedScope?.title     || "Parsing your brief…";
  const summary   = parsedScope?.summary   || parsedScope?.subtitle || "";
  const reviewMsg = parsedScope?.review_message || "";
  const approved  = parsedScope ? parsedScope.approved !== false : false;
  const recType   = parsedScope?.recommended_type || null;
  const recReason = parsedScope?.recommended_type_reason || "";

  const [typeDecision, setTypeDecision] = React.useState(() =>
    parsedScope?.accepted_type ? "accept" : null
  );
  const [anchorEntity, setAnchorEntity] = React.useState("");
  const [anchorEntitySaved, setAnchorEntitySaved] = React.useState(false);
  const [anchorWarning, setAnchorWarning] = React.useState(null);
  const [anchorChangedWarning, setAnchorChangedWarning] = React.useState(null);

  // Grouped question state — prefers persisted groups, then intake groups, then flat list
  const [qGroups, setQGroups] = React.useState(() => {
    if (parsedScope?.question_groups?.length) return parsedScope.question_groups;
    return [{ theme: "Research Questions", questions: parsedScope?.questions || [] }];
  });

  // Grouped parameter state — prefers persisted groups, then intake groups, then flat list
  const [pGroups, setPGroups] = React.useState(() => {
    if (parsedScope?.parameter_groups?.length) return parsedScope.parameter_groups;
    const items = parsedScope?.parameters || [];
    return items.length ? [{ group: null, items }] : [];
  });

  const [exclusions,  setExclusions]  = React.useState(parsedScope?.exclusions || []);
  const [showExcl,    setShowExcl]    = React.useState((parsedScope?.exclusions || []).length > 0);
  const [dirty,       setDirty]       = React.useState(false);
  const [undoItem,    setUndoItem]    = React.useState(null);
  const [saving,      setSaving]      = React.useState(false);
  const [saveError,   setSaveError]   = React.useState(null);
  const [liveApproved,   setLiveApproved]   = React.useState(approved);
  const [liveReviewMsg,  setLiveReviewMsg]  = React.useState(reviewMsg);

  const TYPE_LABELS = { lit: "Literature Review", company: "Company Intelligence", tech: "Technology Landscape", position: "Competitive Position" };

  const displayMsg = liveReviewMsg
    .replace(/^STATUS:\s*(APPROVED|REJECTED)[.:]\s*/i, "")
    .replace(/\s*\n?STATUS:\s*(APPROVED|REJECTED)[.:]*\s*$/i, "")
    .replace(/\nTYPE_RECOMMENDATION:.*$/i, "")
    .trim();

  const handleGoNext = () => {
    const accepted = recType && typeDecision === "accept" ? recType : null;
    goNext(accepted);
  };

  const mark = () => setDirty(true);

  const scheduleUndo = (label, restore) => {
    setUndoItem(prev => { if (prev?.timer) clearTimeout(prev.timer); return null; });
    const timer = setTimeout(() => setUndoItem(null), 6000);
    setUndoItem({ label, restore, timer });
  };

  // ── Question group helpers ──────────────────────────────────────────────
  const updateQTheme = (gi, val) => {
    setQGroups(prev => prev.map((g, i) => i === gi ? { ...g, theme: val } : g));
    mark();
  };
  const updateQ = (gi, qi, val) => {
    setQGroups(prev => prev.map((g, i) => {
      if (i !== gi) return g;
      const qs = [...g.questions]; qs[qi] = val; return { ...g, questions: qs };
    }));
    mark();
  };
  const deleteQ = (gi, qi) => {
    const deleted = qGroups[gi].questions[qi];
    const snap = qGroups.map(g => ({ ...g, questions: [...g.questions] }));
    scheduleUndo(`"${deleted.slice(0, 50) || "question"}"`, () => { setQGroups(snap); mark(); });
    setQGroups(prev => {
      const updated = prev.map((g, i) => {
        if (i !== gi) return g;
        return { ...g, questions: g.questions.filter((_, j) => j !== qi) };
      });
      return updated.filter(g => g.questions.length > 0);
    });
    mark();
  };
  const addQ = (gi) => {
    setQGroups(prev => prev.map((g, i) => i === gi ? { ...g, questions: [...g.questions, ""] } : g));
    mark();
  };
  const addQGroup = () => {
    setQGroups(prev => [...prev, { theme: "New Theme", questions: [""] }]);
    mark();
  };
  const deleteQGroup = (gi) => {
    const snap = qGroups.map(g => ({ ...g, questions: [...g.questions] }));
    scheduleUndo(`theme "${qGroups[gi].theme || "Unnamed"}"`, () => { setQGroups(snap); mark(); });
    setQGroups(prev => prev.filter((_, i) => i !== gi));
    mark();
  };

  // ── Parameter group helpers ─────────────────────────────────────────────
  const updatePGroup = (gi, val) => {
    setPGroups(prev => prev.map((g, i) => i === gi ? { ...g, group: val } : g));
    mark();
  };
  const updateP = (gi, pi, val) => {
    setPGroups(prev => prev.map((g, i) => {
      if (i !== gi) return g;
      const items = [...g.items]; items[pi] = val; return { ...g, items };
    }));
    mark();
  };
  const deleteP = (gi, pi) => {
    const deleted = pGroups[gi].items[pi];
    const snap = pGroups.map(g => ({ ...g, items: [...g.items] }));
    scheduleUndo(`"${deleted.slice(0, 50) || "field"}"`, () => { setPGroups(snap); mark(); });
    setPGroups(prev => prev.map((g, i) => {
      if (i !== gi) return g;
      return { ...g, items: g.items.filter((_, j) => j !== pi) };
    }));
    mark();
  };
  const addP = (gi) => {
    setPGroups(prev => prev.map((g, i) => i === gi ? { ...g, items: [...g.items, ""] } : g));
    mark();
  };
  const addPGroup = () => {
    setPGroups(prev => [...prev, { group: "Per entry", items: [""] }]);
    mark();
  };
  const deletePGroup = (gi) => {
    const snap = pGroups.map(g => ({ ...g, items: [...g.items] }));
    scheduleUndo(`group "${pGroups[gi].group || "Unnamed"}"`, () => { setPGroups(snap); mark(); });
    setPGroups(prev => prev.filter((_, i) => i !== gi));
    mark();
  };

  // ── Exclusion helpers ───────────────────────────────────────────────────
  const updateExcl = (i, val) => { setExclusions(prev => { const n=[...prev]; n[i]=val; return n; }); mark(); };
  const deleteExcl = (i) => {
    const deleted = exclusions[i];
    const snap = [...exclusions];
    scheduleUndo(`"${deleted.slice(0, 50) || "exclusion"}"`, () => { setExclusions(snap); mark(); });
    setExclusions(prev => prev.filter((_,j)=>j!==i));
    mark();
  };
  const addExcl = () => { setExclusions(prev => [...prev, ""]); mark(); };

  // ── Save ────────────────────────────────────────────────────────────────
  const handleSave = async (overrideAcceptedType = null) => {
    if (!reportId) return;
    const emptyThemes = qGroups.filter(g => g.questions.filter(q => q.trim()).length === 0);
    if (emptyThemes.length > 0) {
      setSaveError(`Every theme needs at least one question. "${emptyThemes[0].theme}" has none.`);
      return;
    }
    setSaving(true); setSaveError(null);
    const effectiveAcceptedType = overrideAcceptedType ?? (typeDecision === "accept" ? recType : null);
    if (overrideAcceptedType) setTypeDecision("accept");
    try {
      const flatQ = qGroups.flatMap(g => g.questions).filter(q => q.trim());
      const flatP = pGroups.flatMap(g => g.items).filter(p => p.trim());
      const resp = await fetch(`/api/scope/${reportId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          questions: flatQ,
          parameters: flatP,
          exclusions,
          question_groups: qGroups,
          parameter_groups: pGroups,
          accepted_type: effectiveAcceptedType,
          anchor_entity: (effectiveAcceptedType === "position") ? anchorEntity.trim() : undefined,
        }),
      });
      if (!resp.ok) throw new Error(await resp.text());
      const data = await resp.json();
      setLiveApproved(data.approved ?? liveApproved);
      setLiveReviewMsg(data.review_message ?? liveReviewMsg);
      if (data.reconstructed) {
        if (data.question_groups?.length) setQGroups(data.question_groups);
        if (data.parameter_groups?.length) setPGroups(data.parameter_groups);
      }
      setDirty(false);
      if (typeDecision === "accept" && recType === "position") {
        setAnchorEntitySaved(true);
        setAnchorWarning(data.anchor_warning || null);
      }
      if (data.anchor_changed_warning) {
        setAnchorChangedWarning(data.anchor_changed_warning);
      }
    } catch (e) {
      setSaveError(e.message);
    } finally {
      setSaving(false);
    }
  };

  const multiQGroups = qGroups.length > 1;
  const multiPGroups = pGroups.length > 1;
  const totalParams  = pGroups.reduce((s, g) => s + g.items.length, 0);

  return (
    <div className="canvas-inner">
      {readOnly && (
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "8px 14px", marginBottom: 12,
          background: "var(--ink-1)", border: "1px solid var(--ink-2)", borderRadius: "var(--radius)",
          fontSize: 12, color: "var(--ink-4)" }}>
          <Icon name="info" size={13} />
          This report has been researched. The scope is view-only.
        </div>
      )}

      {/* Review verdict */}
      <div className={`review-stamp ${liveApproved ? "approved" : "rejected"}`}>
        <div className="ic"><Icon name={liveApproved ? "checkSmall" : "x"} size={16} strokeWidth={2.4} /></div>
        <div className="text">
          {saving
            ? <span style={{ color: "var(--ink-4)", fontStyle: "italic" }}>Re-reviewing…</span>
            : displayMsg || (liveApproved ? "Scope approved." : "Revisions needed.")}
        </div>
        <span className="meta">{new Date().toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" })}</span>
      </div>

      {/* Type recommendation advisory */}
      {liveApproved && recType && typeDecision === null && (
        <div style={{ display:"flex", alignItems:"flex-start", gap:12, background:"var(--bg-2)", border:"1px solid var(--line-2)", borderRadius:10, padding:"14px 16px", marginBottom:4 }}>
          <div style={{ fontSize:16, lineHeight:1 }}>💡</div>
          <div style={{ flex:1, fontSize:13.5, lineHeight:1.6, color:"var(--ink-2)" }}>
            <strong style={{ color:"var(--ink)" }}>Report type suggestion:</strong>{" "}
            The review agent recommends switching to <strong>{TYPE_LABELS[recType] || recType}</strong>.{" "}
            {recReason}
          </div>
          <div style={{ display:"flex", gap:8, flexShrink:0 }}>
            <button className="btn primary sm" onClick={() => recType === "position" ? setTypeDecision("accept") : handleSave(recType)}>Switch type</button>
            <button className="btn ghost sm" onClick={() => setTypeDecision("dismiss")}>Keep original</button>
          </div>
        </div>
      )}
      {liveApproved && recType && typeDecision === "accept" && (
        <div style={{ background:"var(--bg-2)", border:"1px solid var(--line-2)", borderRadius:10, padding:"10px 16px", marginBottom:4, fontSize:13, color:"var(--ink-3)" }}>
          <div style={{ display:"flex", alignItems:"center", gap:10 }}>
            <Icon name="checkSmall" size={14} />
            Report type will be set to <strong style={{ color:"var(--ink-2)", marginLeft:4 }}>{TYPE_LABELS[recType] || recType}</strong>.
            <button onClick={() => { setTypeDecision(null); setAnchorEntity(""); }} style={{ marginLeft:"auto", fontSize:11, fontFamily:"var(--mono)", background:"none", border:"none", cursor:"pointer", color:"var(--ink-4)" }}>undo</button>
          </div>
          {recType === "position" && (
            <div style={{ marginTop:10 }}>
              <div style={{ fontSize:12, color:"var(--ink-3)", marginBottom:4 }}>Your company or technology <span style={{ color:"var(--red, #c0392b)" }}>*</span></div>
              <div style={{ display:"flex", gap:8, alignItems:"center" }}>
                <input
                  type="text"
                  placeholder="e.g. Acme Bio — GalNAc-conjugated siRNA platform"
                  value={anchorEntity}
                  onChange={e => { setAnchorEntity(e.target.value); setAnchorEntitySaved(false); setAnchorWarning(null); }}
                  onKeyDown={e => { if (e.key === "Enter" && anchorEntity.trim().length >= 2) { e.preventDefault(); handleSave(); } }}
                  style={{ flex:1, fontSize:13, padding:"7px 10px", borderRadius:6, border:"1px solid var(--line-2)", background:"var(--bg)", color:"var(--ink)", boxSizing:"border-box" }}
                />
                <button
                  className="btn primary sm"
                  disabled={anchorEntity.trim().length < 2 || saving || anchorEntitySaved}
                  onClick={() => handleSave()}
                >
                  {saving ? "Confirming…" : anchorEntitySaved ? "Confirmed ✓" : "Confirm"}
                </button>
              </div>
              {anchorEntitySaved && anchorWarning && (
                <div style={{ marginTop:6, fontSize:12, color:"var(--amber, #b45309)", background:"var(--amber-bg, #fffbeb)", border:"1px solid var(--amber-line, #fcd34d)", borderRadius:6, padding:"6px 10px" }}>
                  ⚠ {anchorWarning} — you can still proceed or change the entity.
                </div>
              )}
              {anchorEntitySaved && !anchorWarning && (
                <div style={{ marginTop:6, fontSize:12, color:"var(--green, #16a34a)" }}>
                  ✓ Re-assessed with <strong>{anchorEntity.trim()}</strong>. You can now generate the outline.
                </div>
              )}
              {!anchorEntitySaved && (
                <div style={{ fontSize:11, color:"var(--ink-4)", marginTop:4 }}>
                  Enter your entity and click Confirm — the scope agent will re-assess before moving to the outline.
                </div>
              )}
              {anchorChangedWarning && (
                <div style={{ marginTop:8, fontSize:12, color:"var(--amber, #b45309)", background:"var(--amber-bg, #fffbeb)", border:"1px solid var(--amber-line, #fcd34d)", borderRadius:6, padding:"8px 10px" }}>
                  ⚠ {anchorChangedWarning}
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* Exec summary — only shown when approved */}
      {liveApproved && <div className="outline-summary">
<h2>{title}</h2>
        {summary && <p>{summary}</p>}
        {qGroups.length > 0 && (() => {
          const totalQ = qGroups.reduce((s, g) => s + g.questions.length, 0);
          const themes = qGroups.map(g => g.theme).filter(Boolean);
          const themeStr = themes.length > 1
            ? themes.slice(0, -1).join(", ") + " and " + themes[themes.length - 1]
            : themes[0] || null;
          return (
            <p>
              The report will address <strong>{totalQ} research question{totalQ !== 1 ? "s" : ""}</strong>
              {themeStr ? <> structured around <strong>{themeStr}</strong></> : ""}.
            </p>
          );
        })()}
      </div>}

      {liveApproved && <div className="scope-doc" style={readOnly ? { pointerEvents: "none", opacity: 0.72 } : undefined}>

        {/* ── Research Questions ── */}
        <div style={{ marginBottom:28 }}>
          <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:14 }}>
            <div className="scope-section-label">Research Questions</div>
            <button className="scope-add-btn" onClick={addQGroup}>+ Add theme</button>
          </div>

          {qGroups.map((group, gi) => (
            <div key={gi} className="scope-group">
              <ThemeLabel
                value={group.theme}
                onChange={val => updateQTheme(gi, val)}
                onDelete={() => deleteQGroup(gi)}
                showDelete={multiQGroups}
              />
              {group.questions.map((q, qi) => (
                <ScopeRow
                  key={qi}
                  prefix={`${qi + 1}.`}
                  value={q}
                  onChange={val => updateQ(gi, qi, val)}
                  onDelete={() => deleteQ(gi, qi)}
                  placeholder="Research question…"
                />
              ))}
              <button className="scope-add-btn" style={{ marginLeft:28 }} onClick={() => addQ(gi)}>+ Add question</button>
            </div>
          ))}
        </div>

        {/* ── Parameters ── */}
        {(totalParams > 0 || pGroups.length > 0) && (
          <div style={{ marginBottom:28 }}>
            <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:14 }}>
              <div className="scope-section-label">
                {state.reportType === "scout" ? "Fields to capture per entry" :
                 state.reportType === "company" ? "Fields to capture per company" :
                 "Capture Parameters"}
              </div>
              {multiPGroups && (
                <button className="scope-add-btn" onClick={addPGroup}>+ Add group</button>
              )}
            </div>

            {pGroups.map((group, gi) => (
              <div key={gi} className="scope-group">
                {(multiPGroups || group.group) && (
                  <ThemeLabel
                    value={group.group || ""}
                    onChange={val => updatePGroup(gi, val)}
                    onDelete={() => deletePGroup(gi)}
                    showDelete={multiPGroups}
                  />
                )}
                {group.items.map((item, pi) => (
                  <ScopeRow
                    key={pi}
                    prefix="—"
                    value={item}
                    onChange={val => updateP(gi, pi, val)}
                    onDelete={() => deleteP(gi, pi)}
                    placeholder="Field to capture…"
                  />
                ))}
                <button className="scope-add-btn" style={{ marginLeft:28 }} onClick={() => addP(gi)}>
                  {multiPGroups ? "+ Add field" : "+ Add field"}
                </button>
              </div>
            ))}

            {!multiPGroups && (
              <button className="scope-add-btn" style={{ marginTop:4 }} onClick={addPGroup}>+ Add group</button>
            )}
          </div>
        )}

        {/* ── Exclusions ── */}
        {showExcl ? (
          <div style={{ marginBottom:16 }}>
            <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:10 }}>
              <div className="scope-section-label">Out of Scope</div>
              <button className="scope-add-btn" onClick={addExcl}>+ Add</button>
            </div>
            {exclusions.length === 0 && (
              <div style={{ fontSize:13, color:"var(--ink-4)", fontStyle:"italic", marginLeft:28 }}>None — click + Add to add one</div>
            )}
            {exclusions.map((item, i) => (
              <ScopeRow key={i} prefix="—" value={item} onChange={val => updateExcl(i, val)} onDelete={() => deleteExcl(i)} placeholder="Out of scope item…" />
            ))}
          </div>
        ) : (
          <button className="scope-add-btn" style={{ marginBottom:12 }} onClick={() => setShowExcl(true)}>+ Add out-of-scope items</button>
        )}
      </div>}

      {/* Action bar — save state integrated */}
      <div className="actionbar">
        <div className="left" style={{ display:"flex", alignItems:"center", gap:10 }}>
          {readOnly
            ? <span style={{ color: "var(--ink-4)", fontSize: 12 }}>View only</span>
            : <span>Scope written to <span className="kbd">scope.md</span></span>}
        </div>
        <div className="right">
          <button className="btn ghost" onClick={goBack}><Icon name="arrowLeft" size={14} /> {readOnly ? "Back" : "Edit brief"}</button>
          {readOnly && <button className="btn ghost" onClick={goForward}>View outline <Icon name="arrowRight" size={14} /></button>}
          {!readOnly && (dirty ? (
            <div style={{ display:"flex", flexDirection:"column", alignItems:"flex-end", gap:3 }}>
              <button className="btn primary lg" onClick={() => handleSave()} disabled={saving}>
                {saving ? "Re-assessing…" : "Re-assess Scope"}
              </button>
              <span style={{ color:"var(--ink-4)", fontSize:11 }}>Your edits will be sent to the review agent for re-approval.</span>
              {saveError && <span style={{ color:"var(--red, #c0392b)", fontSize:12 }}>{saveError}</span>}
            </div>
          ) : (
            <button
              className="btn primary lg"
              disabled={!liveApproved || loading || saving || (recType && typeDecision === null) || (recType === "position" && typeDecision === "accept" && !anchorEntitySaved)}
              onClick={handleGoNext}
              title={
                recType && typeDecision === null ? "Accept or dismiss the type suggestion above first" :
                (recType === "position" && typeDecision === "accept" && !anchorEntitySaved) ? "Confirm your company or technology name above first" : ""
              }
            >
              {loading ? "Generating outline…" : "Generate outline"}
              {!loading && <Icon name="arrowRight" size={14} />}
            </button>
          ))}
        </div>
      </div>

      {undoItem && (
        <div className="undo-toast">
          <span>Removed {undoItem.label}</span>
          <button onClick={() => {
            undoItem.restore();
            clearTimeout(undoItem.timer);
            setUndoItem(null);
          }}>Undo</button>
        </div>
      )}
    </div>
  );
}

window.StepScope = StepScope;
