// StationPanel — the inspector/editor for a selected station node in the
// line-setup workspace (Slice 4). COMPOSITE tier: pure renderer, no fetching. It
// has two modes chosen by `readOnly`: an inspect view (Task 7 — also what a locked,
// launched line shows) and an EDIT view (Task 8) whose every control emits an op
// through `onEdit(op)` — the page owns the working copy and applies ops via
// window.GraphEdit. See COMPONENTS.md.
//
// Props: { node, template, templates, features, edges, nodes, readOnly, onEdit(op), onClose }
//   node      — the selected graph node { id, templateId, title, instructions,
//               humanReview, covers, origin, edited }
//   template  — the matching line template { id, title, description, ... } | undefined
//   templates — ALL station templates [{ id, title, description, humanReview }] (edit: the <select>)
//   features  — the plan's features [{ key, title, phase }] (to resolve/pick `covers`)
//   edges     — the graph's full edge list [{ from, to, kind }]
//   nodes     — the graph's full node list (edit: the add-edge endpoint <select>s)
//   onEdit(op) — op = { type, … } dispatched by the page through window.GraphEdit
//
// Op shapes emitted: rename{id,title} · setTemplate{id,templateId} ·
//   setInstructions{id,text} · toggleHumanReview{id} · setCovers{id,keys} ·
//   addEdge{edge} · removeEdge{edge} · removeNode{id}. The parent remounts this
//   panel per selection (`key={node.id}`), so local UI state resets each node.

// eslint-disable-next-line no-unused-vars
function StationPanel({ node, template, templates, features, edges, nodes, readOnly, onEdit, onClose }) {
  const { useState } = React;
  // Hooks run before the guard (rules of hooks); the parent only mounts us with a node.
  const [addFrom, setAddFrom] = useState(node ? node.id : '');
  const [addTo, setAddTo] = useState('');
  const [addKind, setAddKind] = useState('flow');
  const [confirmRemove, setConfirmRemove] = useState(false);

  if (!node) return null;
  const emit = (op) => onEdit && onEdit(op);
  const featureByKey = new Map((features || []).map((f) => [f.key, f]));
  const covers = Array.isArray(node.covers) ? node.covers : [];
  const allEdges = Array.isArray(edges) ? edges : [];
  const allNodes = Array.isArray(nodes) ? nodes : [];
  const allTemplates = Array.isArray(templates) ? templates : [];
  const templateIds = new Set(allTemplates.map((t) => t.id));
  const inbound = allEdges.filter((e) => e.to === node.id);
  const outbound = allEdges.filter((e) => e.from === node.id);
  const touching = allEdges.filter((e) => e.from === node.id || e.to === node.id);
  const nodeIds = allNodes.map((n) => n.id);

  const section = (title, body) => (
    <div className="px-4 py-3 border-b border-neutral-100">
      <div className="text-[10px] font-bold uppercase tracking-widest text-neutral-400 mb-1.5">{title}</div>
      {body}
    </div>
  );

  const kindChip = (kind) => (
    <span className={`shrink-0 rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide ${kind === 'rework' ? 'bg-orange-100 text-orange-700' : 'bg-slate-100 text-slate-600'}`}>
      {kind === 'rework' ? 'rework' : 'flow'}
    </span>
  );

  // ── read-only inspector (Task 7 — also the locked/launched view) ──────────────
  const readOnlyEdgeRow = (e, dir) => {
    const other = dir === 'in' ? e.from : e.to;
    return (
      <li key={`${e.from}->${e.to}:${e.kind}`} className="flex items-center gap-2 text-xs">
        {kindChip(e.kind)}
        <span className="text-neutral-400">{dir === 'in' ? '←' : '→'}</span>
        <span className="font-mono text-neutral-700 truncate">{other}</span>
      </li>
    );
  };

  const readOnlyBody = (
    <div className="flex-1 min-h-0 overflow-y-auto">
      {template && template.description && section('Template',
        <p className="text-sm text-neutral-600">{template.description}</p>
      )}

      {section('Instructions',
        node.instructions
          ? <pre className="whitespace-pre-wrap text-sm text-neutral-800 font-sans">{node.instructions}</pre>
          : <p className="text-sm text-neutral-400 italic">No instructions yet.</p>
      )}

      {section('Covers',
        covers.length
          ? (
            <ul className="space-y-1">
              {covers.map((key) => {
                const f = featureByKey.get(key);
                return (
                  <li key={key} className="text-sm text-neutral-700 flex items-center gap-2">
                    <span className="w-1.5 h-1.5 rounded-full bg-indigo-400 shrink-0" />
                    <span className="truncate">{f ? f.title : key}</span>
                    {f && f.phase && <span className="text-[10px] uppercase tracking-wide text-neutral-400">{f.phase}</span>}
                  </li>
                );
              })}
            </ul>
          )
          : <p className="text-sm text-neutral-400 italic">Covers no features.</p>
      )}

      {section('Connections',
        (inbound.length || outbound.length)
          ? (
            <ul className="space-y-1.5">
              {inbound.map((e) => readOnlyEdgeRow(e, 'in'))}
              {outbound.map((e) => readOnlyEdgeRow(e, 'out'))}
            </ul>
          )
          : <p className="text-sm text-neutral-400 italic">No connections.</p>
      )}

      {node.origin && section('Origin',
        <span className="text-xs font-mono text-neutral-500">{node.origin}</span>
      )}
    </div>
  );

  // ── edit view (Task 8) ────────────────────────────────────────────────────────
  const editBody = (
    <div className="flex-1 min-h-0 overflow-y-auto">
      {section('Title',
        <input
          type="text"
          value={node.title}
          onChange={(e) => emit({ type: 'rename', id: node.id, title: e.target.value })}
          placeholder="Station title"
          className="w-full rounded-lg border border-neutral-300 px-2.5 py-1.5 text-sm text-neutral-800 focus:outline-none focus:ring-2 focus:ring-indigo-500"
        />
      )}

      {section('Template',
        <select
          value={node.templateId}
          onChange={(e) => emit({ type: 'setTemplate', id: node.id, templateId: e.target.value })}
          className="w-full rounded-lg border border-neutral-300 px-2.5 py-1.5 text-sm text-neutral-800 bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
        >
          {!templateIds.has(node.templateId) && (
            <option value={node.templateId}>{(node.templateId || '—') + ' (unknown)'}</option>
          )}
          {allTemplates.map((t) => (
            <option key={t.id} value={t.id}>{t.title || t.id}</option>
          ))}
        </select>
      )}

      {section('Instructions',
        <textarea
          rows={5}
          value={node.instructions}
          onChange={(e) => emit({ type: 'setInstructions', id: node.id, text: e.target.value })}
          placeholder="What this station does…"
          className="w-full rounded-lg border border-neutral-300 px-2.5 py-1.5 text-sm text-neutral-800 font-sans resize-y focus:outline-none focus:ring-2 focus:ring-indigo-500"
        />
      )}

      {section('Human review',
        <label className="flex items-center justify-between cursor-pointer">
          <span className="text-sm text-neutral-600">Require human review here</span>
          <button
            role="switch"
            aria-checked={!!node.humanReview}
            onClick={() => emit({ type: 'toggleHumanReview', id: node.id })}
            className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1 ${node.humanReview ? 'bg-indigo-600' : 'bg-neutral-200'}`}
          >
            <span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${node.humanReview ? 'translate-x-6' : 'translate-x-1'}`} />
          </button>
        </label>
      )}

      {section(`Covers (${covers.length})`,
        (features && features.length)
          ? (
            <div className="space-y-1.5">
              {features.map((f) => {
                const on = covers.includes(f.key);
                return (
                  <label key={f.key} className="flex items-center gap-2 text-sm text-neutral-700 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={on}
                      onChange={() => {
                        const next = on ? covers.filter((k) => k !== f.key) : [...covers, f.key];
                        emit({ type: 'setCovers', id: node.id, keys: next });
                      }}
                      className="rounded border-neutral-300 text-indigo-600 focus:ring-indigo-500"
                    />
                    <span className="truncate">{f.title || f.key}</span>
                    {f.phase && <span className="text-[10px] uppercase tracking-wide text-neutral-400">{f.phase}</span>}
                  </label>
                );
              })}
            </div>
          )
          : <p className="text-sm text-neutral-400 italic">No plan features to cover.</p>
      )}

      {section('Connections',
        <div className="space-y-2">
          {touching.length
            ? (
              <ul className="space-y-1.5">
                {touching.map((e) => (
                  <li key={`${e.from}->${e.to}:${e.kind}`} className="flex items-center gap-2 text-xs">
                    {kindChip(e.kind)}
                    <span className="font-mono text-neutral-700 truncate flex-1">
                      {e.from} <span className="text-neutral-400">→</span> {e.to}
                    </span>
                    <button
                      onClick={() => emit({ type: 'removeEdge', edge: { from: e.from, to: e.to, kind: e.kind } })}
                      className="shrink-0 w-5 h-5 flex items-center justify-center rounded text-neutral-400 hover:text-red-600 hover:bg-red-50"
                      title="Remove connection"
                      aria-label={`Remove ${e.kind} edge ${e.from} to ${e.to}`}
                    >×</button>
                  </li>
                ))}
              </ul>
            )
            : <p className="text-sm text-neutral-400 italic">No connections yet.</p>}

          <div className="flex items-center gap-1.5 pt-1">
            <select
              value={addFrom}
              onChange={(e) => setAddFrom(e.target.value)}
              aria-label="Edge from"
              className="min-w-0 flex-1 rounded border border-neutral-300 px-1.5 py-1 text-xs bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
            >
              {nodeIds.map((id) => (<option key={id} value={id}>{id}</option>))}
            </select>
            <span className="text-neutral-400 text-xs shrink-0">→</span>
            <select
              value={addTo}
              onChange={(e) => setAddTo(e.target.value)}
              aria-label="Edge to"
              className="min-w-0 flex-1 rounded border border-neutral-300 px-1.5 py-1 text-xs bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
            >
              <option value="">to…</option>
              {nodeIds.map((id) => (<option key={id} value={id}>{id}</option>))}
            </select>
            <select
              value={addKind}
              onChange={(e) => setAddKind(e.target.value)}
              aria-label="Edge kind"
              className="shrink-0 rounded border border-neutral-300 px-1.5 py-1 text-xs bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
            >
              <option value="flow">flow</option>
              <option value="rework">rework</option>
            </select>
            <button
              disabled={!addTo || addFrom === addTo}
              onClick={() => { emit({ type: 'addEdge', edge: { from: addFrom, to: addTo, kind: addKind } }); setAddTo(''); }}
              className="shrink-0 rounded bg-indigo-600 px-2 py-1 text-xs font-semibold text-white hover:bg-indigo-700 disabled:opacity-40 disabled:cursor-not-allowed"
            >Add</button>
          </div>
        </div>
      )}

      <div className="px-4 py-3">
        {confirmRemove ? (
          <div className="rounded-lg border border-red-200 bg-red-50 p-3">
            <div className="text-sm font-semibold text-red-800 mb-2">
              Really remove? This drops {touching.length} edge{touching.length === 1 ? '' : 's'}.
            </div>
            <div className="flex items-center gap-2">
              <button
                onClick={() => emit({ type: 'removeNode', id: node.id })}
                className="rounded-lg bg-red-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-red-700"
              >Remove station</button>
              <button
                onClick={() => setConfirmRemove(false)}
                className="rounded-lg border border-neutral-300 px-3 py-1.5 text-xs font-semibold text-neutral-600 hover:bg-neutral-100"
              >Cancel</button>
            </div>
          </div>
        ) : (
          <button
            onClick={() => setConfirmRemove(true)}
            className="w-full rounded-lg border border-red-200 px-3 py-2 text-sm font-semibold text-red-700 hover:bg-red-50"
          >Remove station</button>
        )}
      </div>
    </div>
  );

  return (
    // min-h-0: as a flex item (e.g. inside StationModal's max-h card) the panel
    // must be allowed to shrink below its content, or it blows past the cap and
    // the card's overflow-hidden clips the bottom instead of the body scrolling.
    <div className="flex flex-col h-full min-h-0">
      <div className="px-4 py-3 border-b border-neutral-200 flex items-start justify-between gap-3">
        <div className="min-w-0">
          <div className="font-bold text-neutral-800 truncate">{node.title || node.id}</div>
          <div className="mt-1 flex items-center gap-1.5 flex-wrap">
            <span className="text-[10px] font-semibold uppercase tracking-wide bg-neutral-100 text-neutral-500 rounded px-1.5 py-0.5">
              {template ? template.title : (node.templateId || '—')}
            </span>
            {node.humanReview && (
              <span className="text-[10px] font-bold uppercase tracking-wide bg-amber-100 text-amber-700 rounded px-1.5 py-0.5">Human review</span>
            )}
            {Array.isArray(node.edited) && node.edited.length > 0 && (
              <span className="text-[10px] font-bold uppercase tracking-wide bg-indigo-100 text-indigo-700 rounded px-1.5 py-0.5">Edited</span>
            )}
            {node.origin === 'added' && (
              <span className="text-[10px] font-bold uppercase tracking-wide bg-emerald-100 text-emerald-700 rounded px-1.5 py-0.5">Added</span>
            )}
          </div>
        </div>
        <button
          onClick={() => onClose && onClose()}
          className="shrink-0 w-7 h-7 flex items-center justify-center rounded-lg text-neutral-400 hover:text-neutral-700 hover:bg-neutral-100"
          title="Close"
          aria-label="Close"
        >×</button>
      </div>

      {readOnly ? readOnlyBody : editBody}

      {readOnly && (
        <div className="px-4 py-2 border-t border-neutral-100 text-[11px] text-neutral-400">
          Read-only — to change the line, ask in the line chat.
        </div>
      )}
    </div>
  );
}

window.StationPanel = StationPanel;
