// Model pane — fully editable React Flow diagram + a Summary subtab listing
// blocks/associations/constraints/requirements with a click-to-jump UX +
// review controls (Keep / Discard) on analyzer-suggested or analyzer-deprecated
// elements.

"use client";

import { useState } from "react";
import { PaneFrame } from "../PaneFrame";
import { PaneViewTabs, PaneFilterChip } from "../PaneControls";
import { StatusChip } from "../StatusChip";
import { DiagramCanvas } from "../../diagram-canvas/DiagramCanvas";
import { useModelStore } from "../../../lib/sync/ModelStore";
import { useAnalysis } from "../../../lib/workspace/analysisStore";
import { useEditorPaneContext } from "./paneContext";
import { useOpenPanes } from "../../../lib/workspace/openPanesStore";
import {
  decideElement,
  removeBlock,
  removeAssociation,
  removeConstraint,
  removeRequirement,
  type ReviewableElementKind,
} from "../../../lib/sync/ops";
import type { ReviewStatus, SysMLModel } from "../../../lib/sysml/model";

interface ModelPaneProps {
  index: number;
  onClose: () => void;
}

type Tab = "diagram" | "summary";

export function ModelPane({ index, onClose }: ModelPaneProps) {
  const [tab, setTab] = useState<Tab>("diagram");
  const [pendingOnly, setPendingOnly] = useState(false);
  const { model, issuesByElement } = useModelStore();
  const { analyze, inFlight } = useAnalysis();
  const { focusBlockId, setFocusBlockId, projectId } = useEditorPaneContext();
  const running = inFlight.has("model") || inFlight.has("all");

  const pendingCount = countPending(model);

  const right = (
    <div className="pane-controls">
      <PaneViewTabs<Tab>
        value={tab}
        onChange={setTab}
        ariaLabel="Model view mode"
        tabs={[
          { value: "diagram", label: "Diagram" },
          { value: "summary", label: "Summary" },
        ]}
      />
      <PaneFilterChip
        active={pendingOnly}
        onToggle={() => {
          // Pending now overlays the current view mode rather than replacing
          // it. If we're on Diagram and the user wants to triage pending
          // items, switching to Summary makes far more sense than rendering
          // a filtered diagram, so we still nudge to Summary on toggle-on.
          setPendingOnly(p => {
            if (!p && tab === "diagram") setTab("summary");
            return !p;
          });
        }}
        label="Pending"
        count={pendingCount}
        title="Show only suggestions and deprecated model elements"
      />
      <button
        type="button"
        className="pane-action"
        onClick={() => void analyze("model")}
        disabled={running}
        title="Re-derive model from prose"
      >
        {running ? "Analyzing…" : "Analyze"}
      </button>
    </div>
  );

  const subtitle =
    pendingCount > 0
      ? `${model.blocks.length} blocks · ${model.associations.length} assocs · ${model.constraints.length} constraints · ${pendingCount} pending`
      : `${model.blocks.length} blocks · ${model.associations.length} assocs · ${model.constraints.length} constraints`;

  return (
    <PaneFrame title="Model" subtitle={subtitle} right={right} onClose={onClose}>
      {tab === "diagram" && !pendingOnly ? (
        <div className="canvas-scroll canvas-scroll-diagram">
          <DiagramCanvas
            focusBlockId={focusBlockId}
            onSelect={setFocusBlockId}
            issuesByElement={issuesByElement}
            projectId={projectId}
          />
        </div>
      ) : (
        <ModelSummary pendingOnly={pendingOnly} parentIndex={index} />
      )}
    </PaneFrame>
  );
}

function countPending(model: SysMLModel): number {
  const isPending = (rs?: ReviewStatus) => rs === "suggested" || rs === "deprecated";
  return (
    model.blocks.filter(b => isPending(b.reviewStatus)).length +
    model.associations.filter(a => isPending(a.reviewStatus)).length +
    model.constraints.filter(c => isPending(c.reviewStatus)).length +
    model.requirements.filter(r => isPending(r.reviewStatus)).length
  );
}

function ModelSummary({ pendingOnly, parentIndex }: { pendingOnly: boolean; parentIndex: number }) {
  const { model, apply } = useModelStore();
  const { pushFrom } = useOpenPanes();

  const filterPending = <T extends { reviewStatus?: ReviewStatus }>(xs: T[]): T[] =>
    pendingOnly ? xs.filter(x => x.reviewStatus === "suggested" || x.reviewStatus === "deprecated") : xs;

  const blocks = filterPending(model.blocks);
  const associations = filterPending(model.associations);
  const constraints = filterPending(model.constraints);
  const requirements = filterPending(model.requirements);

  const totalShown = blocks.length + associations.length + constraints.length + requirements.length;

  if (totalShown === 0) {
    return (
      <div className="pane-empty">
        {pendingOnly ? (
          <>No pending changes. Everything is up to date.</>
        ) : (
          <>
            No model yet. Click <strong>Analyze</strong> to derive one from your prose, or open the
            diagram and start dragging.
          </>
        )}
      </div>
    );
  }

  const decideKeep = (kind: ReviewableElementKind, id: string) =>
    apply([decideElement({ kind, id })]);
  const decideDiscard = (kind: ReviewableElementKind, id: string) => {
    if (kind === "block") apply([removeBlock(id)]);
    else if (kind === "association") apply([removeAssociation(id)]);
    else if (kind === "constraint") apply([removeConstraint(id)]);
    else if (kind === "requirement") apply([removeRequirement(id)]);
  };

  return (
    <div className="model-summary">
      {blocks.length > 0 && (
        <>
          <h3 className="model-summary-h">Blocks ({blocks.length})</h3>
          <ul className="model-summary-list">
            {blocks.map(b => (
              <li key={b.id}>
                <ReviewRow status={b.reviewStatus}>
                  <button
                    type="button"
                    className="model-summary-row"
                    onClick={() => pushFrom(parentIndex, { kind: "block", id: b.id })}
                  >
                    <span className="model-summary-kind">{b.kind}</span>
                    <span className="model-summary-label">{b.label}</span>
                  </button>
                  {b.linkedTermId ? (
                    <button
                      type="button"
                      className="model-summary-link"
                      title="Open concept detail"
                      onClick={() =>
                        pushFrom(parentIndex, { kind: "term", id: b.linkedTermId! })
                      }
                    >
                      ↪ concept
                    </button>
                  ) : null}
                  <DecideButtons
                    status={b.reviewStatus}
                    onKeep={() => decideKeep("block", b.id)}
                    onDiscard={() => decideDiscard("block", b.id)}
                  />
                </ReviewRow>
              </li>
            ))}
          </ul>
        </>
      )}
      {associations.length > 0 && (
        <>
          <h3 className="model-summary-h">Associations ({associations.length})</h3>
          <ul className="model-summary-list">
            {associations.map(a => (
              <li key={a.id}>
                <ReviewRow status={a.reviewStatus}>
                  <button
                    type="button"
                    className="model-summary-row"
                    onClick={() => pushFrom(parentIndex, { kind: "association", id: a.id })}
                  >
                    <span className="model-summary-kind">{a.kind}</span>
                    <span className="model-summary-label">
                      {labelOf(model, a.fromBlockId)} <em>{a.label || "→"}</em>{" "}
                      {labelOf(model, a.toBlockId)}
                    </span>
                  </button>
                  <DecideButtons
                    status={a.reviewStatus}
                    onKeep={() => decideKeep("association", a.id)}
                    onDiscard={() => decideDiscard("association", a.id)}
                  />
                </ReviewRow>
              </li>
            ))}
          </ul>
        </>
      )}
      {constraints.length > 0 && (
        <>
          <h3 className="model-summary-h">Constraints ({constraints.length})</h3>
          <ul className="model-summary-list">
            {constraints.map(c => (
              <li key={c.id}>
                <ReviewRow status={c.reviewStatus}>
                  <button
                    type="button"
                    className="model-summary-row"
                    onClick={() => pushFrom(parentIndex, { kind: "constraint", id: c.id })}
                  >
                    <span className="model-summary-kind">constraint</span>
                    <span className="model-summary-label">
                      {c.label}
                      {c.expression ? <> — <code>{c.expression}</code></> : null}
                    </span>
                  </button>
                  <DecideButtons
                    status={c.reviewStatus}
                    onKeep={() => decideKeep("constraint", c.id)}
                    onDiscard={() => decideDiscard("constraint", c.id)}
                  />
                </ReviewRow>
              </li>
            ))}
          </ul>
        </>
      )}
      {requirements.length > 0 && (
        <>
          <h3 className="model-summary-h">Requirements ({requirements.length})</h3>
          <ul className="model-summary-list">
            {requirements.map(r => (
              <li key={r.id}>
                <ReviewRow status={r.reviewStatus}>
                  <button
                    type="button"
                    className="model-summary-row"
                    onClick={() => pushFrom(parentIndex, { kind: "requirement", id: r.id })}
                  >
                    <span className="model-summary-kind">{r.tag}</span>
                    <span className="model-summary-label">{r.text}</span>
                  </button>
                  <DecideButtons
                    status={r.reviewStatus}
                    onKeep={() => decideKeep("requirement", r.id)}
                    onDiscard={() => decideDiscard("requirement", r.id)}
                  />
                </ReviewRow>
              </li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
}

function ReviewRow({
  status,
  children,
}: {
  status?: ReviewStatus;
  children: React.ReactNode;
}) {
  return (
    <div className={`model-summary-row-wrap model-status-${status ?? "accepted"}`}>
      {status === "suggested" ? <StatusChip variant="suggested" /> : null}
      {status === "deprecated" ? <StatusChip variant="deprecated" /> : null}
      {children}
    </div>
  );
}

function DecideButtons({
  status,
  onKeep,
  onDiscard,
}: {
  status?: ReviewStatus;
  onKeep: () => void;
  onDiscard: () => void;
}) {
  if (status !== "suggested" && status !== "deprecated") return null;
  return (
    <span className="model-decide-row">
      <button
        type="button"
        className="term-decide term-decide-keep"
        onClick={e => {
          e.stopPropagation();
          onKeep();
        }}
        title={
          status === "suggested" ? "Accept this analyzer suggestion" : "Pin this element despite the analyzer dropping it"
        }
      >
        Keep
      </button>
      <button
        type="button"
        className="term-decide term-decide-discard"
        onClick={e => {
          e.stopPropagation();
          onDiscard();
        }}
        title={status === "suggested" ? "Reject this suggestion" : "Remove this element"}
      >
        Discard
      </button>
    </span>
  );
}

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