// Outline / Model / Requirements sections, each independently collapsible.
// The whole rail can also collapse to a 36px vertical strip.
//
// M5: Model + Requirements sections read from the canonical SysMLModel via
// useModelStore() so renames in either canvas reflect here immediately.
// Outline section is still narrative-derived and uses the fixture (M6 will
// migrate it to the live ProseMirror outline).

"use client";

import { useState } from "react";
import type { FixtureData } from "../../lib/fixtures/aristotle";
import type { ValidationIssue, Severity } from "../../lib/sysml/validate";
import { useModel } from "../../lib/sync/ModelStore";

interface LeftRailProps {
  data: FixtureData;
  focusBlockId: string | null;
  setFocusBlockId: (id: string | null) => void;
  /** Map keyed by element key (block id, `req:<id>`, `assoc:<id>`, …) → issues. */
  issuesByElement?: Map<string, ValidationIssue[]>;
}

function maxSeverityForKey(map: Map<string, ValidationIssue[]> | undefined, key: string): Severity | null {
  const items = map?.get(key);
  if (!items || items.length === 0) return null;
  if (items.some(i => i.severity === "error")) return "error";
  if (items.some(i => i.severity === "warning")) return "warning";
  return "soft";
}

function IssueDot({ severity, title }: { severity: Severity | null; title?: string }) {
  if (!severity) return null;
  return <span className={`rail-issue-dot rail-issue-dot-${severity}`} title={title} />;
}

export function LeftRail({ focusBlockId, setFocusBlockId, issuesByElement }: LeftRailProps) {
  const [collapsed, setCollapsed] = useState(false);
  const [open, setOpen] = useState({ outline: true, model: true, requirements: true });
  const toggle = (k: keyof typeof open) => setOpen(s => ({ ...s, [k]: !s[k] }));
  const model = useModel();

  if (collapsed) {
    return (
      <nav className="leftrail leftrail-collapsed">
        <button
          className="rail-collapse-btn"
          onClick={() => setCollapsed(false)}
          title="Expand rail"
          type="button"
        >
          ›
        </button>
        <div className="rail-collapsed-stack">
          <span className="rail-collapsed-tag" title="Outline">OUT</span>
          <span className="rail-collapsed-tag" title={`Model · ${model.blocks.length + model.constraints.length} elements`}>MOD</span>
          <span className="rail-collapsed-tag" title="Requirements">REQ</span>
        </div>
      </nav>
    );
  }

  // Combine blocks + constraints in the Model section, sorted by kind for a
  // predictable order: system → block → actor → constraint.
  const kindRank: Record<string, number> = { system: 0, block: 1, actor: 2, constraint: 3 };
  const modelEntries: Array<{
    id: string;
    label: string;
    kind: "block" | "actor" | "constraint" | "system";
    propertyCount: number;
  }> = [
    ...model.blocks.map(b => ({
      id: b.id,
      label: b.label,
      kind: b.kind,
      propertyCount: b.properties.length,
    })),
    ...model.constraints.map(c => ({
      id: c.id,
      label: c.label,
      kind: "constraint" as const,
      propertyCount: 0,
    })),
  ].sort((a, b) => {
    const r = (kindRank[a.kind] ?? 99) - (kindRank[b.kind] ?? 99);
    return r !== 0 ? r : a.label.localeCompare(b.label);
  });

  return (
    <nav className="leftrail">
      <div className="rail-section">
        <button className="rail-section-head" onClick={() => toggle("outline")} type="button">
          <span className={`rail-caret ${open.outline ? "rail-caret-open" : ""}`}>▸</span>
          <span className="rail-label">Outline</span>
        </button>
        {open.outline && (
          <ul className="rail-list">
            <li className="rail-item rail-item-active">
              <span className="rail-item-text">Problem framing</span>
            </li>
            <li className="rail-item">
              <span className="rail-item-text">Constraints</span>
              <span className="rail-count rail-count-req">3</span>
            </li>
            <li className="rail-item">
              <span className="rail-item-text">Why now</span>
            </li>
            <li className="rail-item rail-item-muted">
              <span className="rail-item-text">Hypotheses</span>
              <span className="rail-count rail-count-asm">3</span>
            </li>
            <li className="rail-item rail-item-muted">
              <span className="rail-item-text">Open questions</span>
              <span className="rail-count rail-count-q">5</span>
            </li>
            <li className="rail-item rail-item-muted">
              <span className="rail-item-text">Risks</span>
              <span className="rail-count rail-count-risk">2</span>
            </li>
          </ul>
        )}
      </div>

      <div className="rail-section">
        <button className="rail-section-head" onClick={() => toggle("model")} type="button">
          <span className={`rail-caret ${open.model ? "rail-caret-open" : ""}`}>▸</span>
          <span className="rail-label">Model</span>
        </button>
        {open.model && (
          <ul className="rail-list rail-blocks">
            {modelEntries.map(b => {
              const sev = maxSeverityForKey(issuesByElement, b.id);
              const tooltip = issuesByElement?.get(b.id)?.map(i => `${i.code}: ${i.message}`).join("\n");
              return (
                <li
                  key={b.id}
                  className={`rail-block rail-${b.kind} ${focusBlockId === b.id ? "rail-block-active" : ""}`}
                  onMouseEnter={() => setFocusBlockId(b.id)}
                  onMouseLeave={() => setFocusBlockId(null)}
                  onClick={() => setFocusBlockId(b.id)}
                  style={{ cursor: "pointer" }}
                >
                  <span className="rail-block-glyph">
                    {b.kind === "constraint" ? "{}" : b.kind === "actor" ? "◐" : b.kind === "system" ? "◎" : "▢"}
                  </span>
                  <span className="rail-block-label">{b.label}</span>
                  <IssueDot severity={sev} title={tooltip} />
                  {b.kind !== "constraint" && (
                    <span
                      className="rail-block-count"
                      title={`${b.propertyCount} ${b.propertyCount === 1 ? "property" : "properties"}`}
                    >
                      <span className="rail-block-count-glyph">·</span>
                      {b.propertyCount}
                    </span>
                  )}
                </li>
              );
            })}
          </ul>
        )}
      </div>

      <div className="rail-section">
        <button className="rail-section-head" onClick={() => toggle("requirements")} type="button">
          <span className={`rail-caret ${open.requirements ? "rail-caret-open" : ""}`}>▸</span>
          <span className="rail-label">Requirements</span>
        </button>
        {open.requirements && (
          <ul className="rail-list">
            {model.requirements.map(r => {
              const key = `req:${r.id}`;
              const sev = maxSeverityForKey(issuesByElement, key);
              const tooltip = issuesByElement?.get(key)?.map(i => `${i.code}: ${i.message}`).join("\n");
              const traced = r.relations.some(rel => rel.kind === "satisfy");
              return (
                <li key={r.id} className="rail-req">
                  <span className="req-tag">{r.tag}</span>
                  {sev ? (
                    <IssueDot severity={sev} title={tooltip} />
                  ) : (
                    <span className={`req-status ${traced ? "req-traced" : "req-untraced"}`} />
                  )}
                </li>
              );
            })}
          </ul>
        )}
      </div>

      <button
        className="rail-collapse-btn rail-collapse-btn-bottom"
        onClick={() => setCollapsed(true)}
        title="Collapse rail"
        type="button"
      >
        ‹
      </button>
    </nav>
  );
}
