// Detail-column panes for the Finder-style stack.
//
// Each column takes its own subject id (termId, blockId, etc.) and renders
// in the same `.pane` shell as the section panes, so resize / close / header
// behavior is consistent across the stack.
//
// Click handlers inside these columns call `pushFrom(index, ...)` to drill
// further (e.g. clicking a linked block on a term column pushes a block
// column to its right). The `index` prop is the column's own position in
// the stack — so child pushes can truncate everything to its right.

"use client";

import { useEffect, useRef, useState, type ReactNode } from "react";
import { PaneFrame } from "../PaneFrame";
import { StatusChip } from "../StatusChip";
import { useAnalysis, type ClientTerm } from "../../../lib/workspace/analysisStore";
import { useModelStore } from "../../../lib/sync/ModelStore";
import { useOpenPanes } from "../../../lib/workspace/openPanesStore";
import { ContextualSocratesThread } from "../../socrates/ContextualSocratesThread";
import { PromoteToolbar } from "../PromoteToolbar";
import {
  decideElement,
  removeBlock,
  removeAssociation,
  removeConstraint,
  removeRequirement,
  type ReviewableElementKind,
} from "../../../lib/sync/ops";
import type { ReviewStatus, SysMLModel } from "../../../lib/sysml/model";

// ─── Term column ────────────────────────────────────────────────────────

interface TermColumnProps {
  termId: string;
  index: number;
  onClose: () => void;
}

export function TermColumn({ termId, index, onClose }: TermColumnProps) {
  const { getTerm, terms, requirements, findings } = useAnalysis();
  const { model } = useModelStore();
  const { pushFrom } = useOpenPanes();

  const term = getTerm(termId);
  if (!term) {
    return (
      <PaneFrame title="Concept" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This concept no longer exists.</div>
      </PaneFrame>
    );
  }

  const parents = buildParentChain(term, terms);
  const children = terms.filter(t => t.parentId === term.id);
  const linkedBlock = term.linkedBlockId
    ? model.blocks.find(b => b.id === term.linkedBlockId) ?? null
    : null;
  const linkedAssociations = model.associations.filter(a => a.linkedTermId === term.id);
  const linkedConstraints = model.constraints.filter(c => c.linkedTermId === term.id);
  const linkedReqsFromModel = model.requirements.filter(r => r.linkedTermId === term.id);
  const linkedReqsFromAnalyze = requirements.filter(r => r.linkedTermId === term.id);
  const relatedFindings = linkedBlock
    ? findings.filter(f => f.linkedElementIds.includes(linkedBlock.id))
    : findings.filter(f => f.linkedElementIds.includes(`term:${term.id}`));

  const hasFormalism =
    !!linkedBlock ||
    linkedAssociations.length > 0 ||
    linkedConstraints.length > 0 ||
    linkedReqsFromModel.length > 0 ||
    linkedReqsFromAnalyze.length > 0;

  return (
    <PaneFrame
      title={term.label}
      subtitle="concept"
      onClose={onClose}
    >
      <div className="column-body">
        <DefinitionSection term={term} />

        {(parents.length > 0 || children.length > 0 || term.synonyms.length > 0) && (
          <Section label="Hierarchy">
            {parents.length > 0 && (
              <Row label="Parents">
                {parents.map((p, i) => (
                  <span key={p.id}>
                    {i > 0 ? " › " : null}
                    <button
                      type="button"
                      className="termdetail-chip"
                      onClick={() => pushFrom(index - 1, { kind: "term", id: p.id })}
                    >
                      {p.label}
                    </button>
                  </span>
                ))}
              </Row>
            )}
            {children.length > 0 && (
              <Row label="Children">
                {children.map(c => (
                  <button
                    key={c.id}
                    type="button"
                    className="termdetail-chip"
                    onClick={() => pushFrom(index, { kind: "term", id: c.id })}
                  >
                    {c.label}
                  </button>
                ))}
              </Row>
            )}
            {term.synonyms.length > 0 && (
              <Row label="Synonyms">
                {term.synonyms.map(s => (
                  <span key={s} className="termdetail-synonym">
                    {s}
                  </span>
                ))}
              </Row>
            )}
          </Section>
        )}

        <Section label="Promote to formal element">
          <PromoteToolbar term={term} />
        </Section>

        <Section label="Formalisms">
          {!hasFormalism ? (
            <p className="termdetail-empty">
              Not yet formalized. Promote it above to make it a block, association, constraint, or requirement.
            </p>
          ) : (
            <ul className="termdetail-formalism-list">
              {linkedBlock && (
                <li>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "block", id: linkedBlock.id })}
                  >
                    <span className="termdetail-formalism-kind">{linkedBlock.kind}</span>
                    <span className="termdetail-formalism-label">{linkedBlock.label}</span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              )}
              {linkedAssociations.map(a => (
                <li key={a.id}>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "association", id: a.id })}
                  >
                    <span className="termdetail-formalism-kind">{a.kind}</span>
                    <span className="termdetail-formalism-label">
                      {labelOf(model, a.fromBlockId)} <em>{a.label || "→"}</em>{" "}
                      {labelOf(model, a.toBlockId)}
                    </span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              ))}
              {linkedConstraints.map(c => (
                <li key={c.id}>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "constraint", id: c.id })}
                  >
                    <span className="termdetail-formalism-kind">constraint</span>
                    <span className="termdetail-formalism-label">
                      {c.label}
                      {c.expression ? <> — <code>{c.expression}</code></> : null}
                    </span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              ))}
              {linkedReqsFromModel.map(r => (
                <li key={`m-${r.id}`}>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "requirement", id: r.id })}
                  >
                    <span className="termdetail-formalism-kind">{r.tag}</span>
                    <span className="termdetail-formalism-label">{r.text}</span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              ))}
              {linkedReqsFromAnalyze
                .filter(r => !linkedReqsFromModel.some(m => m.tag === r.tag))
                .map(r => (
                  <li key={`a-${r.id}`}>
                    <div className="termdetail-formalism termdetail-formalism-static">
                      <span className="termdetail-formalism-kind">{r.tag}</span>
                      <span className="termdetail-formalism-label">{r.text}</span>
                    </div>
                  </li>
                ))}
            </ul>
          )}
        </Section>

        {relatedFindings.length > 0 && (
          <Section label={`Findings (${relatedFindings.length})`}>
            <ul className="termdetail-findings">
              {relatedFindings.map(f => (
                <li key={f.id} className={`termdetail-finding termdetail-finding-${f.kind}`}>
                  <button
                    type="button"
                    className="termdetail-finding-btn"
                    onClick={() => pushFrom(index, { kind: "finding", id: f.id })}
                  >
                    <span className="termdetail-finding-kind">{f.kind}</span>
                    <span className="termdetail-finding-text">{f.text}</span>
                  </button>
                </li>
              ))}
            </ul>
          </Section>
        )}
      </div>
    </PaneFrame>
  );
}

// ─── Block column ───────────────────────────────────────────────────────

export function BlockColumn({
  blockId,
  index,
  onClose,
}: {
  blockId: string;
  index: number;
  onClose: () => void;
}) {
  const { model, apply } = useModelStore();
  const { findings } = useAnalysis();
  const { pushFrom } = useOpenPanes();
  const block = model.blocks.find(b => b.id === blockId);

  if (!block) {
    return (
      <PaneFrame title="Block" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This block no longer exists.</div>
      </PaneFrame>
    );
  }

  const associations = model.associations.filter(
    a => a.fromBlockId === block.id || a.toBlockId === block.id
  );
  const requirements = model.requirements.filter(r =>
    r.relations.some(rel => rel.kind === "satisfy" && rel.blockId === block.id)
  );
  const relatedFindings = findings.filter(f => f.linkedElementIds.includes(block.id));

  return (
    <PaneFrame
      title={block.label}
      subtitle={block.kind === "block" ? "block" : `block · ${block.kind}`}
      right={
        <ReviewBadge status={block.reviewStatus}>
          <DecideButtons
            kind="block"
            id={block.id}
            status={block.reviewStatus}
            onKeep={() => apply([decideElement({ kind: "block", id: block.id })])}
            onDiscard={() => apply([removeBlock(block.id)])}
          />
        </ReviewBadge>
      }
      onClose={onClose}
    >
      <div className="column-body">
        {block.linkedTermId && (
          <Section label="Concept">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => pushFrom(index, { kind: "term", id: block.linkedTermId! })}
            >
              ↪ open concept
            </button>
          </Section>
        )}
        {block.properties.length > 0 && (
          <Section label="Properties">
            <ul className="block-prop-list">
              {block.properties.map(p => (
                <li key={p.id} className="block-prop">
                  <span className="block-prop-name">{p.name}</span>
                  <span className="block-prop-type">{p.type.kind}</span>
                </li>
              ))}
            </ul>
          </Section>
        )}
        {associations.length > 0 && (
          <Section label="Associations">
            <ul className="termdetail-formalism-list">
              {associations.map(a => (
                <li key={a.id}>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "association", id: a.id })}
                  >
                    <span className="termdetail-formalism-kind">{a.kind}</span>
                    <span className="termdetail-formalism-label">
                      {labelOf(model, a.fromBlockId)} <em>{a.label || "→"}</em>{" "}
                      {labelOf(model, a.toBlockId)}
                    </span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              ))}
            </ul>
          </Section>
        )}
        {requirements.length > 0 && (
          <Section label="Requirements satisfied">
            <ul className="termdetail-formalism-list">
              {requirements.map(r => (
                <li key={r.id}>
                  <button
                    type="button"
                    className="termdetail-formalism"
                    onClick={() => pushFrom(index, { kind: "requirement", id: r.id })}
                  >
                    <span className="termdetail-formalism-kind">{r.tag}</span>
                    <span className="termdetail-formalism-label">{r.text}</span>
                    <span className="termdetail-formalism-jump">→</span>
                  </button>
                </li>
              ))}
            </ul>
          </Section>
        )}
        {relatedFindings.length > 0 && (
          <Section label={`Findings (${relatedFindings.length})`}>
            <ul className="termdetail-findings">
              {relatedFindings.map(f => (
                <li key={f.id} className={`termdetail-finding termdetail-finding-${f.kind}`}>
                  <button
                    type="button"
                    className="termdetail-finding-btn"
                    onClick={() => pushFrom(index, { kind: "finding", id: f.id })}
                  >
                    <span className="termdetail-finding-kind">{f.kind}</span>
                    <span className="termdetail-finding-text">{f.text}</span>
                  </button>
                </li>
              ))}
            </ul>
          </Section>
        )}
      </div>
    </PaneFrame>
  );
}

// ─── Association column ─────────────────────────────────────────────────

export function AssociationColumn({
  associationId,
  index,
  onClose,
}: {
  associationId: string;
  index: number;
  onClose: () => void;
}) {
  const { model, apply } = useModelStore();
  const { pushFrom } = useOpenPanes();
  const a = model.associations.find(x => x.id === associationId);
  if (!a) {
    return (
      <PaneFrame title="Association" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This association no longer exists.</div>
      </PaneFrame>
    );
  }
  const from = model.blocks.find(b => b.id === a.fromBlockId);
  const to = model.blocks.find(b => b.id === a.toBlockId);

  return (
    <PaneFrame
      title={a.label || "Association"}
      subtitle={a.kind === "association" ? "association" : `association · ${a.kind}`}
      right={
        <ReviewBadge status={a.reviewStatus}>
          <DecideButtons
            kind="association"
            id={a.id}
            status={a.reviewStatus}
            onKeep={() => apply([decideElement({ kind: "association", id: a.id })])}
            onDiscard={() => apply([removeAssociation(a.id)])}
          />
        </ReviewBadge>
      }
      onClose={onClose}
    >
      <div className="column-body">
        <Section label="Endpoints">
          <Row label="From">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => from && pushFrom(index, { kind: "block", id: from.id })}
              disabled={!from}
            >
              {from?.label ?? a.fromBlockId}
            </button>
          </Row>
          <Row label="To">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => to && pushFrom(index, { kind: "block", id: to.id })}
              disabled={!to}
            >
              {to?.label ?? a.toBlockId}
            </button>
          </Row>
        </Section>
        {a.linkedTermId && (
          <Section label="Concept">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => pushFrom(index, { kind: "term", id: a.linkedTermId! })}
            >
              ↪ open concept
            </button>
          </Section>
        )}
      </div>
    </PaneFrame>
  );
}

// ─── Constraint column ──────────────────────────────────────────────────

export function ConstraintColumn({
  constraintId,
  index,
  onClose,
}: {
  constraintId: string;
  index: number;
  onClose: () => void;
}) {
  const { model, apply } = useModelStore();
  const { pushFrom } = useOpenPanes();
  const c = model.constraints.find(x => x.id === constraintId);
  if (!c) {
    return (
      <PaneFrame title="Constraint" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This constraint no longer exists.</div>
      </PaneFrame>
    );
  }
  return (
    <PaneFrame
      title={c.label}
      subtitle="constraint"
      right={
        <ReviewBadge status={c.reviewStatus}>
          <DecideButtons
            kind="constraint"
            id={c.id}
            status={c.reviewStatus}
            onKeep={() => apply([decideElement({ kind: "constraint", id: c.id })])}
            onDiscard={() => apply([removeConstraint(c.id)])}
          />
        </ReviewBadge>
      }
      onClose={onClose}
    >
      <div className="column-body">
        {c.expression && (
          <Section label="Expression">
            <code className="constraint-expr">{c.expression}</code>
          </Section>
        )}
        {c.appliesTo.length > 0 && (
          <Section label="Applies to">
            <ul className="termdetail-formalism-list">
              {c.appliesTo.map(bid => {
                const b = model.blocks.find(x => x.id === bid);
                return (
                  <li key={bid}>
                    <button
                      type="button"
                      className="termdetail-formalism"
                      onClick={() => pushFrom(index, { kind: "block", id: bid })}
                    >
                      <span className="termdetail-formalism-kind">block</span>
                      <span className="termdetail-formalism-label">{b?.label ?? bid}</span>
                      <span className="termdetail-formalism-jump">→</span>
                    </button>
                  </li>
                );
              })}
            </ul>
          </Section>
        )}
        {c.linkedTermId && (
          <Section label="Concept">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => pushFrom(index, { kind: "term", id: c.linkedTermId! })}
            >
              ↪ open concept
            </button>
          </Section>
        )}
      </div>
    </PaneFrame>
  );
}

// ─── Requirement column ─────────────────────────────────────────────────

export function RequirementColumn({
  requirementId,
  index,
  onClose,
}: {
  requirementId: string;
  index: number;
  onClose: () => void;
}) {
  const { model, apply } = useModelStore();
  const { requirements: analyzedReqs, getTerm, decideRequirement } = useAnalysis();
  const { pushFrom } = useOpenPanes();

  // Match by id in either list.
  const modelReq = model.requirements.find(r => r.id === requirementId);
  const analyzedReq = analyzedReqs.find(r => r.id === requirementId);

  if (!modelReq && !analyzedReq) {
    return (
      <PaneFrame title="Requirement" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This requirement no longer exists.</div>
      </PaneFrame>
    );
  }

  const tag = modelReq?.tag ?? analyzedReq?.tag ?? requirementId;
  const text = modelReq?.text ?? analyzedReq?.text ?? "";
  const linkedTermId = modelReq?.linkedTermId ?? analyzedReq?.linkedTermId ?? null;
  const tracedTo = modelReq?.relations
    .filter((r): r is { kind: "satisfy"; blockId: string } => r.kind === "satisfy")
    .map(r => r.blockId) ?? analyzedReq?.tracedToIds ?? [];
  const reviewStatus = modelReq?.reviewStatus;
  const analyzedStatus = analyzedReq?.status;

  return (
    <PaneFrame
      title={tag}
      subtitle="requirement"
      right={
        modelReq ? (
          <ReviewBadge status={reviewStatus}>
            <DecideButtons
              kind="requirement"
              id={modelReq.id}
              status={reviewStatus}
              onKeep={() => apply([decideElement({ kind: "requirement", id: modelReq.id })])}
              onDiscard={() => apply([removeRequirement(modelReq.id)])}
            />
          </ReviewBadge>
        ) : analyzedReq && analyzedStatus !== "accepted" ? (
          <div className="term-decision-row">
            <button
              type="button"
              className="term-decide term-decide-keep"
              onClick={() => void decideRequirement(analyzedReq.id, "keep")}
            >
              Keep
            </button>
            <button
              type="button"
              className="term-decide term-decide-discard"
              onClick={() => void decideRequirement(analyzedReq.id, "discard")}
            >
              Discard
            </button>
          </div>
        ) : null
      }
      onClose={onClose}
    >
      <div className="column-body">
        <Section label="Text">
          <p className="termdetail-def">{text}</p>
        </Section>
        {linkedTermId && (
          <Section label="Concept">
            <button
              type="button"
              className="termdetail-chip"
              onClick={() => pushFrom(index, { kind: "term", id: linkedTermId })}
            >
              {getTerm(linkedTermId)?.label ?? "↪ open concept"}
            </button>
          </Section>
        )}
        {tracedTo.length > 0 && (
          <Section label="Traced to">
            <ul className="termdetail-formalism-list">
              {tracedTo.map(bid => {
                const b = model.blocks.find(x => x.id === bid);
                return (
                  <li key={bid}>
                    <button
                      type="button"
                      className="termdetail-formalism"
                      onClick={() => pushFrom(index, { kind: "block", id: bid })}
                    >
                      <span className="termdetail-formalism-kind">block</span>
                      <span className="termdetail-formalism-label">{b?.label ?? bid}</span>
                      <span className="termdetail-formalism-jump">→</span>
                    </button>
                  </li>
                );
              })}
            </ul>
          </Section>
        )}
      </div>
    </PaneFrame>
  );
}

// ─── Finding column ─────────────────────────────────────────────────────

export function FindingColumn({
  findingId,
  index,
  projectId,
  onClose,
}: {
  findingId: string;
  index: number;
  projectId: string;
  onClose: () => void;
}) {
  const { findings, decideFinding, refresh } = useAnalysis();
  const { pushFrom } = useOpenPanes();
  const f = findings.find(x => x.id === findingId);

  if (!f) {
    return (
      <PaneFrame title="Finding" subtitle="not found" onClose={onClose}>
        <div className="pane-empty">This finding no longer exists.</div>
      </PaneFrame>
    );
  }

  const isPending = f.status === "suggested" || f.status === "deprecated";
  const termAnchors = f.linkedElementIds
    .filter(s => s.startsWith("term:"))
    .map(s => s.slice("term:".length));
  const elementAnchors = f.linkedElementIds.filter(s => !s.startsWith("term:"));

  return (
    <PaneFrame
      title={titleCase(f.kind)}
      subtitle={
        f.severity
          ? `${f.kind} · ${f.severity} · conf ${(f.confidence * 100).toFixed(0)}%`
          : `${f.kind} · conf ${(f.confidence * 100).toFixed(0)}%`
      }
      right={
        isPending ? (
          <div className="term-decision-row">
            <button
              type="button"
              className="term-decide term-decide-keep"
              onClick={() => void decideFinding(f.id, "keep")}
            >
              Keep
            </button>
            <button
              type="button"
              className="term-decide term-decide-discard"
              onClick={() => void decideFinding(f.id, "discard")}
            >
              Dismiss
            </button>
            <button
              type="button"
              className="term-decide term-decide-resolve"
              onClick={() => void decideFinding(f.id, "resolve")}
            >
              Resolve
            </button>
          </div>
        ) : null
      }
      onClose={onClose}
    >
      <div className="column-body">
        <Section label={f.validationCode ? `${f.validationCode} — finding` : "Finding"}>
          <p className="termdetail-def">{f.text}</p>
        </Section>
        {(termAnchors.length > 0 || elementAnchors.length > 0) && (
          <Section label="Anchors">
            {termAnchors.map(tid => (
              <button
                key={tid}
                type="button"
                className="termdetail-chip"
                onClick={() => pushFrom(index, { kind: "term", id: tid })}
              >
                ↪ concept
              </button>
            ))}
            {elementAnchors.map(eid => (
              <button
                key={eid}
                type="button"
                className="termdetail-chip"
                onClick={() => pushFrom(index, { kind: "block", id: eid })}
              >
                ↪ {eid}
              </button>
            ))}
          </Section>
        )}
        <Section label="Discussion">
          <ContextualSocratesThread
            projectId={projectId}
            findingId={f.id}
            findingText={f.text}
            onResolved={() => {
              void refresh();
              onClose();
            }}
          />
        </Section>
      </div>
    </PaneFrame>
  );
}

// ─── Shared helpers ─────────────────────────────────────────────────────

/**
 * Definition section for TermColumn. Read state by default; click anywhere
 * on the definition (or the empty placeholder) to enter edit mode. Save
 * with Cmd/Ctrl-Enter or by clicking Save; cancel with Esc. When the user
 * has authored the definition (definitionPinned), shows a "pinned" chip
 * in the header and a "Reset to AI suggestion" link in edit mode that
 * clears the text + the pin.
 */
function DefinitionSection({ term }: { term: ClientTerm }) {
  const { setTermDefinition } = useAnalysis();
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(term.definition ?? "");
  const textareaRef = useRef<HTMLTextAreaElement | null>(null);

  // When the user opens the editor, sync the draft with the latest text and
  // focus the textarea. Selecting nothing keeps the cursor at the end.
  useEffect(() => {
    if (!editing) return;
    setDraft(term.definition ?? "");
    requestAnimationFrame(() => {
      const el = textareaRef.current;
      if (!el) return;
      el.focus();
      el.setSelectionRange(el.value.length, el.value.length);
    });
    // term.id intentionally excluded from deps — re-running on every term
    // change would clobber an in-flight edit.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [editing]);

  const commit = () => {
    setEditing(false);
    const next = draft.trim();
    const cur = (term.definition ?? "").trim();
    if (next === cur) return;
    void setTermDefinition(term.id, next.length > 0 ? next : null);
  };

  const cancel = () => {
    setEditing(false);
    setDraft(term.definition ?? "");
  };

  const reset = () => {
    setEditing(false);
    setDraft("");
    void setTermDefinition(term.id, null);
  };

  const headerRight = term.definitionPinned ? (
    <StatusChip variant="muted" label="pinned" title="You authored this definition. Future Analyze runs will leave it alone." />
  ) : null;

  if (editing) {
    return (
      <Section label="Definition" right={headerRight}>
        <div className="termdetail-def-edit">
          <textarea
            ref={textareaRef}
            className="termdetail-def-textarea"
            value={draft}
            onChange={e => setDraft(e.target.value)}
            onBlur={commit}
            onKeyDown={e => {
              if (e.key === "Escape") {
                e.preventDefault();
                cancel();
              } else if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
                e.preventDefault();
                commit();
              }
            }}
            placeholder="A short noun-phrase definition…"
            rows={3}
          />
          <div className="termdetail-def-actions">
            <button
              type="button"
              className="termdetail-def-btn termdetail-def-btn-primary"
              onMouseDown={e => {
                // Don't lose focus before commit — onBlur would fire and
                // commit a possibly-stale value race.
                e.preventDefault();
                commit();
              }}
            >
              Save
            </button>
            <button
              type="button"
              className="termdetail-def-btn"
              onMouseDown={e => {
                e.preventDefault();
                cancel();
              }}
            >
              Cancel
            </button>
            {term.definitionPinned ? (
              <button
                type="button"
                className="termdetail-def-link"
                onMouseDown={e => {
                  e.preventDefault();
                  reset();
                }}
                title="Clear the definition and let the next Analyze pass refill it from prose"
              >
                Reset to AI suggestion
              </button>
            ) : null}
            <span className="termdetail-def-hint">⌘↵ to save · Esc to cancel</span>
          </div>
        </div>
      </Section>
    );
  }

  return (
    <Section label="Definition" right={headerRight}>
      {term.definition ? (
        <p
          className="termdetail-def termdetail-def-clickable"
          onClick={() => setEditing(true)}
          role="button"
          tabIndex={0}
          onKeyDown={e => {
            if (e.key === "Enter") {
              e.preventDefault();
              setEditing(true);
            }
          }}
        >
          {term.definition}
        </p>
      ) : (
        <button
          type="button"
          className="termdetail-empty termdetail-def-clickable termdetail-def-empty-btn"
          onClick={() => setEditing(true)}
        >
          Click to write a definition
        </button>
      )}
    </Section>
  );
}

function Section({ label, children, right }: { label: string; children: ReactNode; right?: ReactNode }) {
  return (
    <section className="termdetail-section">
      <header className="termdetail-section-head">
        <h3 className="termdetail-section-h">{label}</h3>
        {right ? <div className="termdetail-section-right">{right}</div> : null}
      </header>
      <div className="termdetail-section-body">{children}</div>
    </section>
  );
}

function Row({ label, children }: { label: string; children: ReactNode }) {
  return (
    <div className="termdetail-row">
      <span className="termdetail-row-label">{label}</span>
      <span className="termdetail-row-body">{children}</span>
    </div>
  );
}

function ReviewBadge({
  status,
  children,
}: {
  status?: ReviewStatus;
  children?: ReactNode;
}) {
  if (status === "suggested" || status === "deprecated") {
    return (
      <div className="column-review-row">
        <StatusChip variant={status} />
        {children}
      </div>
    );
  }
  return null;
}

function DecideButtons({
  status,
  onKeep,
  onDiscard,
}: {
  kind: ReviewableElementKind;
  id: string;
  status?: ReviewStatus;
  onKeep: () => void;
  onDiscard: () => void;
}) {
  if (status !== "suggested" && status !== "deprecated") return null;
  return (
    <span className="term-decision-row">
      <button type="button" className="term-decide term-decide-keep" onClick={onKeep}>
        Keep
      </button>
      <button type="button" className="term-decide term-decide-discard" onClick={onDiscard}>
        Discard
      </button>
    </span>
  );
}

function buildParentChain(
  term: { id: string; parentId: string | null },
  terms: Array<{ id: string; parentId: string | null; label: string }>
): Array<{ id: string; label: string }> {
  const byId = new Map(terms.map(t => [t.id, t]));
  const chain: Array<{ id: string; label: string }> = [];
  let cur = term.parentId ? byId.get(term.parentId) : null;
  const seen = new Set<string>();
  while (cur && !seen.has(cur.id)) {
    seen.add(cur.id);
    chain.unshift({ id: cur.id, label: cur.label });
    cur = cur.parentId ? byId.get(cur.parentId) : null;
  }
  return chain;
}

function labelOf(model: SysMLModel, id: string): string {
  return model.blocks.find(b => b.id === id)?.label ?? id;
}

function titleCase(s: string): string {
  return s.length ? s[0].toUpperCase() + s.slice(1) : s;
}

