import type { ReactElement } from "react";
import { useEffect, useRef, useState } from "react";

import type { HwpodNodeOpsResult, LiveSurface } from "../../types/domain";
import { formatTimestamp, jsonPreview, toneClass } from "../../utils";
import { StateTag } from "../shared/StateTag";

interface HwpodNodeOpsSidebarProps {
  live: LiveSurface | null;
  collapsed: boolean;
}

export function HwpodNodeOpsSidebar({ live, collapsed }: HwpodNodeOpsSidebarProps): ReactElement {
  const [dialog, setDialog] = useState<{ title: string; body: string } | null>(null);
  const payload = live?.hwpodNodeOps?.data ?? null;
  const specPayload = live?.hwpodSpecs?.data ?? null;
  const selectedSpec = specPayload?.specs?.find((item) => item.availability?.ok === true) ?? specPayload?.specs?.[0] ?? null;
  const specResults = selectedSpec?.availability?.results ?? [];
  const results = specResults.length > 0 ? specResults : payload?.results ?? [];
  const firstResult = results[0] ?? null;
  const status = selectedSpec?.availability?.status ?? payload?.status ?? (live?.hwpodNodeOps?.ok ? "completed" : live?.hwpodNodeOps?.error ? "blocked" : "unknown");
  const nodeId = selectedSpec?.nodeId ?? payload?.nodeId ?? (payload?.requestMeta?.nodeId as string | undefined) ?? "未发现";
  const hwpodName = selectedSpec?.name ?? selectedSpec?.hwpodId ?? payload?.hwpodId ?? "未发现";

  return (
    <aside className={`right-sidebar${collapsed ? " is-hwpod-collapsed" : ""}`} id="hwpod-node-sidebar" aria-label="HWPOD node-ops 摘要看板" aria-hidden={collapsed}>
      <div className="right-sidebar-content">
        <header className="right-sidebar-head">
          <div>
            <p className="eyebrow">HWPOD</p>
            <h2>Node Ops</h2>
          </div>
        </header>
        <StateTag id="hwpod-node-status-tag" tone={toneClass(status)}>node-ops {status}</StateTag>
        <section className="hwpod-node-status" aria-label="HWPOD node-ops status">
          <div className="hwpod-node-summary" id="hwpod-node-summary">
            <SummaryTile label="Contract" value={payload?.contractVersion ?? "hwpod-node-ops-v1"} detail="contract" title="Contract" onOpen={() => setDialog({ title: "Contract", body: jsonPreview(payload, 1600) })} />
            <SummaryTile label="Specs" value={String(specPayload?.availableCount ?? specPayload?.count ?? 0)} detail="specs" title="Specs" onOpen={() => setDialog({ title: "Specs", body: jsonPreview(specPayload, 2200) })} />
            <SummaryTile label="Spec" value={hwpodName} detail="spec" title="Spec" onOpen={() => setDialog({ title: "Spec", body: jsonPreview(selectedSpec, 2200) })} />
          </div>
          <dl className="hwpod-node-meta">
            <div><dt>hwpod</dt><dd>{hwpodName}</dd></div>
            <div><dt>node</dt><dd>{nodeId}</dd></div>
            <div><dt>workspace</dt><dd>{selectedSpec?.workspacePath ?? "未发现"}</dd></div>
            <div><dt>case</dt><dd>{String(selectedSpec?.source?.caseId ?? "未声明")}</dd></div>
            <div><dt>route</dt><dd>{payload?.route ?? "/v1/hwpod-node-ops"}</dd></div>
            <div><dt>updated</dt><dd>{formatTimestamp(payload?.observedAt ?? live?.loadedAt)}</dd></div>
          </dl>
        </section>
        <section className="hwpod-node-workspace" aria-label="HWPOD node-ops results">
          <div className="hwpod-node-ops" id="hwpod-node-ops-results">
            <SummaryTile label="Node" value={nodeId} detail="node" title="Node" onOpen={() => setDialog({ title: "Node", body: jsonPreview({ nodeId, selectedSpec, payload }, 2200) })} />
            <SummaryTile label="Ops" value={String(payload?.acceptedOps ?? results.length)} detail="ops" title="Ops" onOpen={() => setDialog({ title: "Ops", body: jsonPreview(results, 1600) })} />
            {results.length === 0 ? <SummaryTile label="probe" value={live?.hwpodSpecs?.error ?? live?.hwpodNodeOps?.error ?? "等待结果"} detail="probe" title="probe" onOpen={() => setDialog({ title: "probe", body: jsonPreview({ hwpodSpecs: live?.hwpodSpecs, hwpodNodeOps: live?.hwpodNodeOps }, 2200) })} /> : results.map((item, index) => <OpTile key={`${item.opId ?? index}`} item={item} index={index} onOpen={() => setDialog({ title: item.op ?? item.opId ?? `op ${index + 1}`, body: jsonPreview(item, 1600) })} />)}
          </div>
          <NodeOpsStream lines={nodeOpsLines(results, firstResult, live?.hwpodSpecs?.error ?? live?.hwpodNodeOps?.error, selectedSpec)} />
        </section>
        <dialog className="hwpod-detail-dialog" id="hwpod-detail-dialog" open={dialog !== null}>
          <form method="dialog">
            <header><strong id="hwpod-detail-title">{dialog?.title ?? "HWPOD"}</strong></header>
            <pre id="hwpod-detail-body">{dialog?.body ?? ""}</pre>
            <button value="close" type="button" onClick={() => setDialog(null)}>关闭</button>
          </form>
        </dialog>
      </div>
    </aside>
  );
}

function SummaryTile({ label, value, detail, title, onOpen }: { label: string; value: string; detail: string; title: string; onOpen(): void }): ReactElement {
  return <button className="summary-tile" type="button" role="button" tabIndex={0} data-hwpod-detail={detail} data-hwpod-title={title} onClick={onOpen}><span>{label}</span><strong>{value}</strong></button>;
}

function OpTile({ item, index, onOpen }: { item: HwpodNodeOpsResult; index: number; onOpen(): void }): ReactElement {
  return <SummaryTile label={item.op ?? `op ${index + 1}`} value={item.ok === false ? item.blocker?.code ?? item.status ?? "blocked" : item.status ?? "completed"} detail={item.opId ?? `op-${index + 1}`} title={item.op ?? "HWPOD op"} onOpen={onOpen} />;
}

function NodeOpsStream({ lines }: { lines: string[] }): ReactElement {
  const [follow, setFollow] = useState(true);
  const scrollRef = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (follow && scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [follow, lines]);
  return (
    <section className="hwpod-event-panel" aria-label="node-ops 流">
      <header>
        <span>node-ops</span>
        <div>
          <button id="hwpod-event-follow" type="button" onClick={() => setFollow((value) => !value)}>{follow ? "跟随" : "暂停"}</button>
          <button id="hwpod-event-jump" type="button" onClick={() => { setFollow(true); if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }}>跳到底部</button>
        </div>
      </header>
      <div className="hwpod-event-scroll" id="hwpod-event-scroll" ref={scrollRef} onScroll={() => { const node = scrollRef.current; if (node && node.scrollHeight - node.clientHeight - node.scrollTop > 24) setFollow(false); }}>
        <pre id="hwpod-event-text">{lines.join("\n") || "等待 HWPOD node-ops。"}</pre>
      </div>
    </section>
  );
}

function nodeOpsLines(results: HwpodNodeOpsResult[], firstResult: HwpodNodeOpsResult | null, error?: string | null, spec?: { name?: string; nodeId?: string; workspacePath?: string; availability?: { status?: string } } | null): string[] {
  const specLine = spec ? [`spec ${spec.name ?? "unknown"} ${spec.nodeId ?? "unknown-node"} ${spec.availability?.status ?? "discovered"} ${spec.workspacePath ?? ""}`.trim()] : [];
  if (results.length > 0) {
    return specLine.concat(results.map((item) => {
      const status = item.ok === false ? item.blocker?.code ?? item.status ?? "blocked" : item.status ?? "completed";
      return `${item.opId ?? "op"} ${item.op ?? "unknown"} ${status}`;
    }));
  }
  if (firstResult) return [`${firstResult.opId ?? "op"} ${firstResult.op ?? "unknown"} ${firstResult.status ?? "observed"}`];
  if (specLine.length > 0) return specLine;
  return error ? [`blocked ${error}`] : [];
}
