// Unified Guidance workspace.
// Keeps the manager-facing model simple while reusing the existing Knowledge,
// Global Rules, Learning Collections, and Insights APIs underneath.

const GUIDANCE_TABS = [
  { id: "knowledge", label: "Knowledge", question: "What should agents know?" },
  { id: "procedures", label: "Procedures", question: "What should agents do when this happens?" },
  { id: "goals", label: "Goals", question: "What result should agents work toward?" },
];

function guidanceApi(path, options = {}) {
  const headers = { ...(options.headers || {}) };
  if (options.body && !headers["Content-Type"]) headers["Content-Type"] = "application/json";
  const envId = typeof window.activeEnvId === "function" ? window.activeEnvId() : null;
  if (envId) headers["X-Environment-Id"] = envId;
  return fetch(path, { ...options, headers }).then(async (response) => {
    const text = await response.text();
    let data = null;
    try { data = text ? JSON.parse(text) : null; } catch { data = { error: text }; }
    if (!response.ok) throw new Error(data?.error || `Request failed (${response.status})`);
    return data;
  });
}

function fileToGuidancePayload(file) {
  const binary = /\.(pdf|docx?|xlsx?|pptx?)$/i.test(file.name);
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = () => reject(new Error("Couldn't read the file"));
    reader.onload = (event) => {
      const result = String(event.target?.result || "");
      resolve({
        name: file.name,
        kind: file.name.split(".").pop()?.toLowerCase() || "doc",
        contentType: file.type || "application/octet-stream",
        encoding: binary ? "base64" : "text",
        content: binary ? (result.split(",")[1] || "") : result,
      });
    };
    if (binary) reader.readAsDataURL(file);
    else reader.readAsText(file);
  });
}

function GuidanceHeader({ tab, onTab, onUpload, uploading }) {
  return (
    <>
      <div className="gd-hero">
        <div>
          <div className="gd-eyebrow">Guidance</div>
          <h1>Shape what your agents know, do, and improve.</h1>
          <p>Upload the documents your team already uses. Citrus separates reference material, procedures, and reusable learnings for your review.</p>
        </div>
        <button className="btn btn-primary gd-upload" onClick={onUpload} disabled={uploading}>
          {uploading ? "Analyzing…" : "Upload guidance"}
        </button>
      </div>
      <div className="gd-tabs" role="tablist" aria-label="Guidance sections">
        {GUIDANCE_TABS.map((item) => (
          <button
            key={item.id}
            type="button"
            role="tab"
            aria-selected={tab === item.id}
            className={`gd-tab${tab === item.id ? " is-active" : ""}`}
            onClick={() => onTab(item.id)}
          >
            <span>{item.label}</span>
            <small>{item.question}</small>
          </button>
        ))}
      </div>
    </>
  );
}

function GuidanceUploadResult({ result, onOpenProcedures, onApproveCandidates, onDismiss }) {
  if (!result) return null;
  const analysis = result.guidanceAnalysis || {};
  const procedureCount = analysis.procedures?.length || 0;
  const learningCount = analysis.learningCandidates?.length || 0;
  const ruleCount = analysis.companyRuleCandidates?.length || 0;
  return (
    <div className="gd-result" role="status">
      <div>
        <div className="gd-result-title">Citrus analyzed {result.name}</div>
        <div className="gd-result-copy">
          {analysis.classification === "reference" ? "Reference material detected." : `${procedureCount} procedure${procedureCount === 1 ? "" : "s"} detected.`}
          {learningCount > 0 ? ` ${learningCount} reusable learning suggestion${learningCount === 1 ? "" : "s"} found.` : ""}
          {ruleCount > 0 ? ` ${ruleCount} Company Rule candidate${ruleCount === 1 ? "" : "s"} found.` : ""}
        </div>
        {analysis.clarification ? <div className="gd-result-question">{analysis.clarification}</div> : null}
      </div>
      <div className="gd-result-actions">
        {procedureCount > 0 ? <button className="btn btn-primary btn-sm" onClick={onOpenProcedures}>Review procedure</button> : null}
        {ruleCount > 0 ? <button className="btn btn-ghost btn-sm" onClick={() => onApproveCandidates("rule")}>Approve Rule candidates</button> : null}
        {learningCount > 0 ? <button className="btn btn-ghost btn-sm" onClick={() => onApproveCandidates("learning")}>Approve Learning candidates</button> : null}
        <button className="btn btn-ghost btn-sm" onClick={onDismiss}>Dismiss</button>
      </div>
    </div>
  );
}

function GuidanceKnowledge({ agents, userRole, authUser, conflicts, onAskCitrus }) {
  const [view, setView] = useState("overview");
  const [relationships, setRelationships] = useState([]);
  const loadRelationships = () => guidanceApi("/guidance/relationships").then(setRelationships).catch(() => setRelationships([]));
  useEffect(() => {
    loadRelationships();
  }, []);
  const cards = [
    { id: "protections", title: "Citrus protections", copy: "Read-only safety and authorization controls.", tone: "shield" },
    { id: "rules", title: "Company rules", copy: "Instructions every company agent must follow.", tone: "rule" },
    { id: "references", title: "Reference playbooks", copy: "Products, pricing, policies, FAQs, and business facts.", tone: "reference" },
    { id: "packs", title: "Learning packs", copy: "Reusable, versioned packages of approved learnings.", tone: "pack" },
  ];

  if (view === "rules") {
    return <GuidanceSubpage title="Company rules" subtitle="Deliberate company-wide instructions." onBack={() => setView("overview")}><window.GlobalRulesTab /></GuidanceSubpage>;
  }
  if (view === "references") {
    return <GuidanceSubpage title="Reference playbooks" subtitle="Approved material agents consult when relevant." onBack={() => setView("overview")}><window.KnowledgeTab agents={agents} conflicts={conflicts} onAskCitrus={onAskCitrus} userRole={userRole} /></GuidanceSubpage>;
  }
  if (view === "packs") {
    return <GuidanceSubpage title="Learning packs" subtitle="Apply consistent learning packages across agents." onBack={() => setView("overview")}><window.LearningCollectionsTab agents={agents} userRole={userRole} authUser={authUser} /></GuidanceSubpage>;
  }
  if (view === "protections") {
    return <GuidanceSubpage title="Citrus protections" subtitle="Non-negotiable platform safeguards." onBack={() => setView("overview")}><CitrusProtections /></GuidanceSubpage>;
  }

  const resolveRelationship = async (relationship, action) => {
    try {
      const extra = {};
      if (action === "merge_canonical") {
        const mergedText = window.prompt("Write the single canonical instruction", relationship.higher.text);
        if (!mergedText) return;
        extra.mergedText = mergedText;
      }
      if (action === "narrow_scope") {
        extra.scope = { type: "one_agent", teamIds: [], agentIds: [relationship.agentId] };
      }
      await guidanceApi(`/guidance/relationships/${relationship.fingerprint}/resolve`, {
        method: "POST",
        body: JSON.stringify({ agentId: relationship.agentId, action, ...extra }),
      });
      window.toast && window.toast(action === "escalate" ? "Guidance conflict escalated" : "Guidance conflict resolved", "good");
      loadRelationships();
    } catch (error) {
      window.toast && window.toast(error.message, "warn");
    }
  };
  const openConflicts = relationships.filter((item) => item.relationship === "conflict" && item.status === "open");
  const reinforcements = relationships.filter((item) =>
    ["reinforcement", "duplicate", "specialization"].includes(item.relationship)
  );

  return (
    <>
      {openConflicts.length > 0 ? <div className="gd-conflicts">
        {openConflicts.slice(0, 5).map((relationship) => <div className="gd-conflict" key={relationship.fingerprint}>
          <div><strong>{relationship.higher.name} conflicts with {relationship.lower.name}</strong><small>{agents.find((agent) => agent.id === relationship.agentId)?.name || relationship.agentId}</small></div>
          <p><b>Effective:</b> {relationship.higher.text}</p>
          <p><b>Lower source:</b> {relationship.lower.text}</p>
          <div className="gd-conflict-actions">
            {relationship.availableActions?.includes("use_higher") ? <button className="btn btn-primary btn-sm" onClick={() => resolveRelationship(relationship, "use_higher")}>Use higher instruction</button> : null}
            {relationship.availableActions?.includes("narrow_scope") ? <button className="btn btn-ghost btn-sm" onClick={() => resolveRelationship(relationship, "narrow_scope")}>Narrow lower scope</button> : null}
            {relationship.availableActions?.includes("merge_canonical") ? <button className="btn btn-ghost btn-sm" onClick={() => resolveRelationship(relationship, "merge_canonical")}>Merge</button> : null}
            {relationship.availableActions?.includes("keep_lower_cancel_assignment") ? <button className="btn btn-ghost btn-sm" onClick={() => resolveRelationship(relationship, "keep_lower_cancel_assignment")}>Keep lower and cancel Pack</button> : null}
            {relationship.availableActions?.includes("exclude_agent") ? <button className="btn btn-ghost btn-sm" onClick={() => resolveRelationship(relationship, "exclude_agent")}>Exclude agent</button> : null}
            {relationship.availableActions?.includes("escalate") ? <button className="btn btn-ghost btn-sm" onClick={() => resolveRelationship(relationship, "escalate")}>Escalate</button> : null}
          </div>
        </div>)}
      </div> : null}
      {reinforcements.length > 0 ? <div className="gd-reinforcement">
        <strong>{reinforcements.length} reinforced instruction{reinforcements.length === 1 ? "" : "s"}</strong>
        <span>Citrus injects each effective instruction once and retains all supporting sources.</span>
      </div> : null}
      <div className="gd-grid">
      {cards.map((card) => (
        <button key={card.id} className={`gd-card gd-card--${card.tone}`} onClick={() => setView(card.id)}>
          <span className="gd-card-kicker">Knowledge</span>
          <strong>{card.title}</strong>
          <span>{card.copy}</span>
          <em>Open →</em>
        </button>
      ))}
      <div className="gd-card gd-card--learning">
        <span className="gd-card-kicker">Experience</span>
        <strong>Learnings grow after agents start working</strong>
        <span>New businesses can operate with roles, protections, and playbooks before their first experience-based learning appears.</span>
      </div>
      </div>
    </>
  );
}

function GuidanceSubpage({ title, subtitle, onBack, children }) {
  return (
    <div className="gd-subpage">
      <div className="gd-subhead">
        <button className="btn btn-ghost btn-sm" onClick={onBack}>← Guidance</button>
        <div><h2>{title}</h2><p>{subtitle}</p></div>
      </div>
      {children}
    </div>
  );
}

function CitrusProtections() {
  const [data, setData] = useState(null);
  useEffect(() => {
    Promise.all([
      guidanceApi("/config/platform-rules").catch(() => ({ rules: [] })),
      guidanceApi("/config/platform-defaults").catch(() => ({ rules: [] })),
    ]).then(([floor, defaults]) => setData({
      rules: floor.rules || [],
      defaults: defaults.rules || [],
    }));
  }, []);
  if (!data) return <div className="gd-empty">Loading Citrus protections…</div>;
  const floor = data.rules || [];
  const defaults = data.defaults || [];
  return (
    <div className="gd-list">
      {[...floor, ...defaults.filter((item) => item.enabled !== false)].map((rule, index) => (
        <div className="gd-row" key={rule.id || index}>
          <span className="gd-row-index">{index + 1}</span>
          <div><strong>{rule.text || rule.label || String(rule)}</strong><small>{index < floor.length ? "Citrus protection · cannot be overridden" : "Operating guideline"}</small></div>
        </div>
      ))}
      {floor.length + defaults.length === 0 ? <div className="gd-empty">No protections returned for this environment.</div> : null}
    </div>
  );
}

function procedureFromDoc(doc, draft = null) {
  // CIT-515: version is server-owned (server/routes/knowledge.js bumps
  // doc.procedure.version itself when meaningful content changes) — this
  // never originates a version number, it only ever reads doc.procedure.version
  // back for display when one already exists.
  if (doc.procedure) return { ...doc.procedure };
  const detected = draft || doc.guidanceAnalysis?.procedures?.[0];
  return {
    title: detected?.title || doc.name,
    trigger: detected?.trigger || "",
    rules: detected?.rules || [],
    steps: detected?.steps || [],
    completion: detected?.completion || "",
    escalation: detected?.escalation || "",
    status: "draft",
  };
}

function ProceduresPanel({ agents, focusDocId }) {
  const [docs, setDocs] = useState([]);
  const [busy, setBusy] = useState(true);
  const [editing, setEditing] = useState(null);
  const [error, setError] = useState("");
  const load = () => {
    setBusy(true);
    guidanceApi("/knowledge")
      .then((items) => {
        const materialized = new Set((items || []).map((doc) => doc.sourceProcedureDraftId).filter(Boolean));
        setDocs((items || []).flatMap((doc) => {
        if (doc.guidanceMode === "procedure") return [{ doc, draft: null, key: doc.id }];
        return (doc.guidanceAnalysis?.procedures || []).filter((draft) => !materialized.has(draft.id)).map((draft) => ({
          doc,
          draft,
          key: `${doc.id}:${draft.id}`,
        }));
        }));
      })
      .catch(() => setDocs([]))
      .finally(() => setBusy(false));
  };
  useEffect(load, []);
  useEffect(() => {
    if (!focusDocId || docs.length === 0) return;
    const row = docs.find((item) => item.doc.id === focusDocId);
    if (row) setEditing({ ...row, procedure: procedureFromDoc(row.doc, row.draft), agentIds: Object.keys(row.doc.taught || {}) });
  }, [focusDocId, docs]);

  const createProcedure = async () => {
    setError("");
    try {
      const doc = await guidanceApi("/knowledge/procedures", {
        method: "POST",
        body: JSON.stringify({ title: "New procedure", trigger: "", steps: [] }),
      });
      setEditing({ doc, draft: null, key: doc.id, procedure: procedureFromDoc(doc), agentIds: [] });
      load();
    } catch (createError) {
      setError(createError.message);
    }
  };

  const save = async (activate) => {
    if (!editing) return;
    setError("");
    if (activate && editing.agentIds.length === 0) {
      setError("Choose at least one agent before activating this Procedure.");
      return;
    }
    if (activate && (!editing.procedure.trigger.trim() || editing.procedure.steps.length === 0)) {
      setError("Add a clear trigger and at least one ordered step before activating.");
      return;
    }
    // CIT-515: version is server-owned — strip whatever version this client
    // was displaying so the server's real bump-on-content-change logic is
    // the only thing that ever sets doc.procedure.version.
    const { version: _clientVersion, ...procedureContent } = editing.procedure;
    const procedure = { ...procedureContent, status: activate ? "active" : "draft" };
    try {
      // CIT-515: appliesTo is now the single source of truth for which
      // agents see this doc — the server derives doc.global/doc.taught
      // from it in the same PATCH, so the separate POST
      // /knowledge/:id/teach call this used to make (to actually apply the
      // selection) is no longer needed, and can't fall out of sync with it.
      let targetDoc = editing.doc;
      if (editing.draft) {
        targetDoc = await guidanceApi(`/knowledge/${editing.doc.id}/procedure-drafts/${editing.draft.id}`, {
          method: "POST",
          body: JSON.stringify({}),
        });
      }
      await guidanceApi(`/knowledge/${targetDoc.id}`, {
        method: "PATCH",
        body: JSON.stringify({
          guidanceMode: "procedure",
          procedure,
          guidanceApprovalStatus: activate ? "active" : "draft",
          ...(activate ? {
            appliesTo: {
              type: agents.length > 0 && editing.agentIds.length === agents.length ? "all_agents" : "selected_agents",
              agentIds: editing.agentIds,
            },
          } : {}),
        }),
      });
      window.toast && window.toast(activate ? "Procedure activated" : "Procedure draft saved", "good");
      setEditing(null);
      load();
    } catch (error) {
      setError(error.message);
      window.toast && window.toast(error.message, "warn");
    }
  };

  if (editing) {
    const p = editing.procedure;
    return (
      <div className="gd-editor">
        <button className="btn btn-ghost btn-sm" onClick={() => setEditing(null)}>← Procedures</button>
        <div className="gd-editor-head"><div><span>Procedure draft</span><h2>{p.title || editing.doc.name}</h2></div><small>Source: {editing.doc.name}</small></div>
        <div className="gd-reinforcement"><strong>When the trigger matches, Citrus follows these steps in order.</strong><span>It only affects the agents you select below. Saving a draft does not activate it.</span></div>
        {error ? <div className="gd-result-question" role="alert">{error}</div> : null}
        <GuidanceField label="Procedure name"><input value={p.title} onChange={(e) => setEditing({ ...editing, procedure: { ...p, title: e.target.value } })} placeholder="Create a quotation" /></GuidanceField>
        <GuidanceField label="When should this run?"><input value={p.trigger} onChange={(e) => setEditing({ ...editing, procedure: { ...p, trigger: e.target.value } })} placeholder="A customer requests a quotation" /></GuidanceField>
        <GuidanceField label="What rules apply?"><textarea value={(p.rules || []).join("\n")} onChange={(e) => setEditing({ ...editing, procedure: { ...p, rules: e.target.value.split("\n").filter(Boolean) } })} placeholder="One rule per line" /></GuidanceField>
        <GuidanceField label="What should the agent do?"><textarea value={(p.steps || []).join("\n")} onChange={(e) => setEditing({ ...editing, procedure: { ...p, steps: e.target.value.split("\n").filter(Boolean) } })} placeholder="One ordered step per line" /></GuidanceField>
        {p.stepReferences?.length ? <div className="gd-reinforcement"><strong>{p.stepReferences.length} canonical Learning reference{p.stepReferences.length === 1 ? "" : "s"}</strong><span>{p.stepReferences.map((reference) => `Step ${reference.stepIndex + 1}: ${reference.text}`).join(" · ")}</span></div> : null}
        <GuidanceField label="How does the agent know it is complete?"><input value={p.completion} onChange={(e) => setEditing({ ...editing, procedure: { ...p, completion: e.target.value } })} /></GuidanceField>
        <GuidanceField label="When should it escalate?"><input value={p.escalation} onChange={(e) => setEditing({ ...editing, procedure: { ...p, escalation: e.target.value } })} /></GuidanceField>
        <GuidanceField label="Which agents use it?">
          <div className="gd-checks">{agents.map((agent) => <label key={agent.id}><input type="checkbox" checked={editing.agentIds.includes(agent.id)} onChange={() => setEditing({ ...editing, agentIds: editing.agentIds.includes(agent.id) ? editing.agentIds.filter((id) => id !== agent.id) : [...editing.agentIds, agent.id] })} />{agent.name}</label>)}</div>
        </GuidanceField>
        <div className="gd-editor-actions"><button className="btn btn-ghost" onClick={() => save(false)}>Save draft</button><button className="btn btn-primary" onClick={() => save(true)}>Approve and activate</button></div>
      </div>
    );
  }

  return (
    <div className="gd-section">
      <div className="gd-section-head"><div><h2>Procedures</h2><p>Tell Citrus what to do when a specific situation happens.</p></div><button className="btn btn-primary btn-sm" onClick={createProcedure}>Create procedure</button></div>
      <div className="gd-reinforcement"><strong>Simple model</strong><span>When this happens → follow these steps → finish or escalate. Uploading an SOP can fill this in automatically, but it is optional.</span></div>
      {error ? <div className="gd-result-question" role="alert">{error}</div> : null}
      {busy ? <div className="gd-empty">Loading procedures…</div> : docs.length === 0 ? (
        <div className="gd-empty"><strong>No procedures detected yet</strong><span>Upload an SOP, handbook, or process document and Citrus will structure it for review.</span></div>
      ) : <div className="gd-list">{docs.map((row) => {
        const { doc, draft } = row;
        const p = procedureFromDoc(doc, draft);
        const runs = doc.procedureRuns || [];
        const completions = runs.filter((run) => run.status === "completed").length;
        const escalations = runs.filter((run) => run.status === "escalated").length;
        return <button className="gd-row gd-row-button" key={row.key} onClick={() => setEditing({ ...row, procedure: p, agentIds: Object.keys(doc.taught || {}) })}><div className="gd-proc-icon">↳</div><div><strong>{p.title || doc.name}</strong><small>{p.trigger ? `Runs when: ${p.trigger}` : "Needs trigger confirmation"} · {p.steps?.length || 0} steps{draft ? ` · Source: ${doc.name}` : ` · ${completions} completed · ${escalations} escalated`}</small></div><span className={`gd-status gd-status--${doc.guidanceApprovalStatus || "draft"}`}>{draft ? "detected" : (doc.guidanceApprovalStatus || "draft")}</span></button>;
      })}</div>}
    </div>
  );
}

function GuidanceField({ label, children }) {
  return <label className="gd-field"><span>{label}</span>{children}</label>;
}

function GoalsPanel({ agents }) {
  const [goals, setGoals] = useState([]);
  const [procedures, setProcedures] = useState([]);
  const [packs, setPacks] = useState([]);
  const [open, setOpen] = useState(false);
  const [advanced, setAdvanced] = useState(false);
  const [error, setError] = useState("");
  const [notice, setNotice] = useState("");
  const emptyDraft = { label: "", metric: "", target: "", unit: "", period: "month", agentIds: [], reviewCadence: "weekly", allowedActions: "", guardrails: "", deadline: "", priority: "100", linkedProcedureIds: [], linkedPackIds: [], guardrailMetrics: "" };
  const [draft, setDraft] = useState(emptyDraft);
  const load = () => guidanceApi("/insights/goals").then((items) => setGoals(items || [])).catch(() => setGoals([]));
  useEffect(() => {
    load();
    guidanceApi("/knowledge").then((items) => setProcedures((items || []).filter((item) => item.guidanceMode === "procedure"))).catch(() => {});
    guidanceApi("/learning-collections").then((items) => setPacks(items || [])).catch(() => {});
  }, []);
  const create = async () => {
    setError("");
    setNotice("");
    if (draft.agentIds.length === 0) {
      setError("Choose at least one agent to own this Goal.");
      return;
    }
    if (!draft.metric.trim()) {
      setError("Describe how Citrus should measure progress.");
      return;
    }
    try {
      await guidanceApi("/insights/goals", {
        method: "POST",
        body: JSON.stringify({
          ...draft,
          target: Number(draft.target),
          objective: draft.label,
          allowedActions: draft.allowedActions.split("\n").filter(Boolean),
          guardrails: draft.guardrails.split("\n").filter(Boolean),
          guardrailMetrics: draft.guardrailMetrics.split("\n").filter(Boolean),
          priority: Number(draft.priority),
        }),
      });
      setOpen(false);
      setAdvanced(false);
      setDraft(emptyDraft);
      setNotice("Goal created. Citrus will show it to the selected agents and evaluate attributable progress on the review cadence.");
      load();
    } catch (error) {
      setError(error.message);
      window.toast && window.toast(error.message, "warn");
    }
  };
  const reviewGoal = async (goal) => {
    setError("");
    setNotice("");
    try {
      const result = await guidanceApi(`/insights/goals/${goal.id}/evaluate`, { method: "POST", body: JSON.stringify({}) });
      const evaluated = result.goal;
      setNotice(`Reviewed ${evaluated.label}: ${evaluated.now} / ${evaluated.target} ${evaluated.unit || ""} from attributable outcomes.`);
      load();
    } catch (reviewError) {
      setError(reviewError.message);
    }
  };
  return (
    <div className="gd-section">
      <div className="gd-section-head"><div><h2>Goals</h2><p>Give selected agents a measurable result to work toward over time.</p></div><button className="btn btn-primary btn-sm" onClick={() => { setOpen(!open); setError(""); }}>{open ? "Cancel" : "Set a goal"}</button></div>
      <div className="gd-reinforcement"><strong>A Goal does not replace instructions.</strong><span>It sets the outcome. Agents still follow Company Rules, Procedures, Learning Packs, and guardrails while pursuing it.</span></div>
      {error ? <div className="gd-result-question" role="alert">{error}</div> : null}
      {notice ? <div className="gd-reinforcement" role="status"><span>{notice}</span></div> : null}
      {open ? <div className="gd-goal-form">
        <GuidanceField label="What result do you want?"><input value={draft.label} onChange={(e) => setDraft({ ...draft, label: e.target.value })} placeholder="Increase qualified revenue month over month" /></GuidanceField>
        <div className="gd-form-grid"><GuidanceField label="How should Citrus measure it?"><input value={draft.metric} onChange={(e) => setDraft({ ...draft, metric: e.target.value })} placeholder="Agent-attributable qualified revenue" /></GuidanceField><GuidanceField label="Target"><div className="gd-inline"><input type="number" value={draft.target} onChange={(e) => setDraft({ ...draft, target: e.target.value })} /><input value={draft.unit} onChange={(e) => setDraft({ ...draft, unit: e.target.value })} placeholder="%" /></div></GuidanceField></div>
        <GuidanceField label="By when?"><input type="date" value={draft.deadline} onChange={(e) => setDraft({ ...draft, deadline: e.target.value })} /></GuidanceField>
        <GuidanceField label="Which agents own it?"><div className="gd-checks">{agents.map((agent) => <label key={agent.id}><input type="checkbox" checked={draft.agentIds.includes(agent.id)} onChange={() => setDraft({ ...draft, agentIds: draft.agentIds.includes(agent.id) ? draft.agentIds.filter((id) => id !== agent.id) : [...draft.agentIds, agent.id] })} />{agent.name}</label>)}</div></GuidanceField>
        <GuidanceField label="What are they allowed to do?"><textarea value={draft.allowedActions} onChange={(e) => setDraft({ ...draft, allowedActions: e.target.value })} placeholder="One approved action per line" /></GuidanceField>
        <GuidanceField label="What must they never violate?"><textarea value={draft.guardrails} onChange={(e) => setDraft({ ...draft, guardrails: e.target.value })} placeholder="One guardrail per line" /></GuidanceField>
        <button className="btn btn-ghost btn-sm" type="button" onClick={() => setAdvanced(!advanced)}>{advanced ? "Hide advanced options" : "Advanced: link approved guidance and resolve competing goals"}</button>
        {advanced ? <>
          <GuidanceField label="Which Procedures may it use?"><div className="gd-checks">{procedures.map((procedure) => <label key={procedure.id}><input type="checkbox" checked={draft.linkedProcedureIds.includes(procedure.id)} onChange={() => setDraft({ ...draft, linkedProcedureIds: draft.linkedProcedureIds.includes(procedure.id) ? draft.linkedProcedureIds.filter((id) => id !== procedure.id) : [...draft.linkedProcedureIds, procedure.id] })} />{procedure.procedure?.title || procedure.name}</label>)}</div></GuidanceField>
          <GuidanceField label="Which Learning Packs may it use?"><div className="gd-checks">{packs.map((pack) => <label key={pack.id}><input type="checkbox" checked={draft.linkedPackIds.includes(pack.id)} onChange={() => setDraft({ ...draft, linkedPackIds: draft.linkedPackIds.includes(pack.id) ? draft.linkedPackIds.filter((id) => id !== pack.id) : [...draft.linkedPackIds, pack.id] })} />{pack.name}</label>)}</div></GuidanceField>
          <div className="gd-form-grid"><GuidanceField label="Priority (lower runs first)"><input type="number" value={draft.priority} onChange={(e) => setDraft({ ...draft, priority: e.target.value })} /></GuidanceField><GuidanceField label="Guardrail metrics for competing Goals"><textarea value={draft.guardrailMetrics} onChange={(e) => setDraft({ ...draft, guardrailMetrics: e.target.value })} placeholder="Complaint rate\nDiscount exception rate" /></GuidanceField></div>
        </> : null}
        <button className="btn btn-primary" disabled={!draft.label.trim() || !draft.target || !draft.metric.trim() || draft.agentIds.length === 0} onClick={create}>Create and assign goal</button>
      </div> : null}
      {goals.length === 0 ? <div className="gd-empty"><strong>No active goals yet</strong><span>Set a measurable outcome after the agent has an approved role, reference material, and procedures.</span></div> : <div className="gd-goals">{goals.map((goal) => {
        const target = Number(goal.target || 0);
        const now = Number(goal.now || 0);
        const progress = target > 0 ? Math.min(100, Math.max(0, Math.round((now / target) * 100))) : 0;
        const ownerNames = agents.filter((agent) => (goal.agentIds || [goal.agentId]).includes(agent.id)).map((agent) => agent.name);
        return <div className="gd-goal" key={goal.id}><div className="gd-goal-top"><div><strong>{goal.label}</strong><small>{goal.metric || goal.unit || "Progress"} · checked {goal.reviewCadence || goal.period || "weekly"}</small></div><span className={`gd-status gd-status--${goal.status || "active"}`}>{goal.status || "active"}</span></div><div className="gd-progress"><span style={{ width: `${progress}%` }} /></div><div className="gd-goal-meta"><span>{now} / {target} {goal.unit || ""}</span><span>Owned by {ownerNames.join(", ") || "no agent"}</span><button className="btn btn-ghost btn-sm" onClick={() => reviewGoal(goal)}>Check progress now</button></div></div>;
      })}</div>}
    </div>
  );
}

function GuidanceTab({ agents = [], userRole, authUser, conflicts = [], onAskCitrus }) {
  const [tab, setTab] = useState("knowledge");
  const [uploading, setUploading] = useState(false);
  const [uploadResult, setUploadResult] = useState(null);
  const [focusProcedureId, setFocusProcedureId] = useState(null);
  const fileRef = useRef(null);
  const upload = async (files) => {
    const file = files?.[0];
    if (!file) return;
    setUploading(true);
    try {
      const payload = await fileToGuidancePayload(file);
      const result = await guidanceApi("/knowledge", { method: "POST", body: JSON.stringify(payload) });
      setUploadResult(result);
      if ((result.guidanceAnalysis?.procedures?.length || 0) > 0) setFocusProcedureId(result.id);
    } catch (error) {
      window.toast && window.toast(error.message, "warn");
    } finally {
      setUploading(false);
      if (fileRef.current) fileRef.current.value = "";
    }
  };
  const approveCandidates = async (kind) => {
    if (!uploadResult) return;
    const candidates = kind === "rule"
      ? uploadResult.guidanceAnalysis?.companyRuleCandidates || []
      : uploadResult.guidanceAnalysis?.learningCandidates || [];
    try {
      for (const candidate of candidates.filter((item) => item.status !== "approved")) {
        await guidanceApi(`/knowledge/${uploadResult.id}/guidance-candidates/${candidate.id}/approve`, {
          method: "POST",
          body: JSON.stringify({
            kind,
            scope: { type: "all_agents", teamIds: [], agentIds: [] },
          }),
        });
        candidate.status = "approved";
      }
      setUploadResult({ ...uploadResult });
      window.toast && window.toast(`${candidates.length} ${kind === "rule" ? "Rule" : "Learning"} candidate(s) approved`, "good");
    } catch (error) {
      window.toast && window.toast(error.message, "warn");
    }
  };
  return (
    <div className="gd-page">
      <input ref={fileRef} type="file" multiple={false} accept=".txt,.md,.csv,.json,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx" hidden onChange={(e) => upload(e.target.files)} />
      <GuidanceHeader tab={tab} onTab={setTab} onUpload={() => fileRef.current?.click()} uploading={uploading} />
      <GuidanceUploadResult result={uploadResult} onDismiss={() => setUploadResult(null)} onApproveCandidates={approveCandidates} onOpenProcedures={() => setTab("procedures")} />
      {tab === "knowledge" ? <GuidanceKnowledge agents={agents} userRole={userRole} authUser={authUser} conflicts={conflicts} onAskCitrus={onAskCitrus} /> : null}
      {tab === "procedures" ? <ProceduresPanel agents={agents} focusDocId={focusProcedureId} /> : null}
      {tab === "goals" ? <GoalsPanel agents={agents} /> : null}
    </div>
  );
}

window.GuidanceTab = GuidanceTab;
