import React from "react";
import { displayTimeLabel, fmtClock, fmtDate } from "./time";
import { createRoot } from "react-dom/client";
import { BaiduNetdiskPage } from "./baidu-netdisk";
import { ClaudeQqPage } from "./claudeqq";
import { CodeQueuePage } from "./code-queue";
import { DecisionCenterPage } from "./decision-center";
import { FileBrowserPage } from "./filebrowser";
import { FindJobPage } from "./findjob";
import { HWLAB_URL, HwlabPage } from "./hwlab";
import { MetNonlinearPage } from "./met-nonlinear";
import { MdtodoPage } from "./mdtodo";
import { canonicalizeKnownRoute, createRouteRegistry, DEFAULT_ACTIVE_TABS, MODULES, pathForTarget, resolveRouteTarget } from "./navigation";
import { OaEventFlowPage } from "./oa-event-flow";
import { PipelinePage } from "./pipeline";
import { ProjectManagerPage } from "./project-manager";
import { TodoNotePage } from "./todo-note";
import { TopStatusBar } from "./top-status";
import { K3sCtlPage } from "./k3sctl";
import { LoadingTitle } from "./loading-indicator";
import { errorMessage, requestJson } from "./unidesk-error";
import { UniDeskErrorBanner } from "./unidesk-error-banner";
import { NotificationProvider, useNotification } from "./notification-context";
import { NotificationPopup, NotificationBanner } from "./notification-popup";
import { readRootJsonAttribute } from "./runtime-config";

type AnyRecord = Record<string, any>;

const cfg: AnyRecord = readRootJsonAttribute("data-config", { apiBaseUrl: "/api", authUsername: "admin" });
const environmentIdentity: AnyRecord = cfg.environment && typeof cfg.environment === "object" ? cfg.environment : {};
const initialCodeQueueOverview = readRootJsonAttribute("data-codex-overview", null);
const h = React.createElement;
const { useEffect, useMemo } = React;
const useState: any = React.useState;
const LoadingContext = React.createContext(false);
const ROUTE_REGISTRY = createRouteRegistry(MODULES);
const fastCodeQueueService = {
  id: "code-queue",
  name: "Code Queue",
  providerId: "D601",
  description: "Code Queue",
  repository: { containerName: "k3s:code-queue" },
  backend: {
    nodeBaseUrl: "k3s://code-queue",
    nodeBindHost: "k3s://unidesk/code-queue",
    nodePort: 4222,
    proxyMode: "k3sctl-adapter-http",
    public: false,
  },
  deployment: {
    mode: "k3sctl-managed",
    adapterServiceId: "k3sctl-adapter",
    k3sServiceId: "code-queue",
  },
  runtime: {
    orchestrator: "k3sctl",
    providerStatus: "loading",
    providerName: "D601",
  },
};

function isDocumentVisible(): boolean {
  return typeof document === "undefined" || document.visibilityState !== "hidden";
}

function isDevEnvironment(identity: AnyRecord): boolean {
  return identity?.environment === "dev" || identity?.namespace === "unidesk-dev";
}

function shortCommit(value: any): string {
  const text = typeof value === "string" ? value : "";
  return text.length >= 7 ? text.slice(0, 7) : text || "unknown";
}

function shellRefreshIntervalMs(moduleId: string, tabId: string): number {
  if (moduleId === "ops" && tabId === "status") return 5_000;
  if (moduleId === "nodes" && tabId === "monitor") return 5_000;
  if (moduleId === "tasks" && (tabId === "dispatch" || tabId === "scheduled" || tabId === "pending")) return 5_000;
  if (moduleId === "nodes" || moduleId === "ops") return 10_000;
  if (moduleId === "apps") return 15_000;
  if (moduleId === "tasks") return 15_000;
  return 30_000;
}

async function loadTaskRawData(task: any): Promise<any> {
  if (!task?._summaryOnly || !task?.id) return task;
  const result = await requestJson(`${cfg.apiBaseUrl}/tasks/${encodeURIComponent(String(task.id))}`);
  return result?.task || task;
}

function taskRawButtonData(task: any): any {
  return task?._summaryOnly ? { ...task, _loadRaw: () => loadTaskRawData(task) } : task;
}


function fmtDuration(seconds: number): string {
  if (!Number.isFinite(seconds)) return "--";
  const safeSeconds = Math.max(0, seconds);
  if (safeSeconds === 0) return "0s";
  if (safeSeconds < 0.01) return "<0.01s";
  if (safeSeconds < 0.1) return `${safeSeconds.toFixed(2)}s`;
  if (safeSeconds < 1) return `${safeSeconds.toFixed(1)}s`;
  if (safeSeconds < 10 && !Number.isInteger(safeSeconds)) return `${safeSeconds.toFixed(1)}s`;
  if (safeSeconds < 60) return `${Math.round(safeSeconds)}s`;
  const wholeSeconds = Math.floor(safeSeconds);
  if (wholeSeconds < 3600) return `${Math.floor(wholeSeconds / 60)}m ${wholeSeconds % 60}s`;
  return `${Math.floor(wholeSeconds / 3600)}h ${Math.floor((wholeSeconds % 3600) / 60)}m`;
}

function fmtMs(value: any): string {
  const ms = Number(value);
  if (!Number.isFinite(ms)) return "--";
  if (ms < 1) return `${Math.max(0, ms).toFixed(1)}ms`;
  if (ms < 10) return `${ms.toFixed(1)}ms`;
  if (ms < 1000) return `${Math.round(ms)}ms`;
  return fmtDuration(ms / 1000);
}

function fmtBytes(value: any): string {
  const bytes = Number(value);
  if (!Number.isFinite(bytes) || bytes <= 0) return "--";
  const units = ["B", "KB", "MB", "GB", "TB"];
  let current = bytes;
  let index = 0;
  while (current >= 1024 && index < units.length - 1) {
    current /= 1024;
    index += 1;
  }
  return `${current.toFixed(index === 0 ? 0 : 1)} ${units[index]}`;
}

function fmtPercent(value: any): string {
  const number = Number(value);
  return Number.isFinite(number) ? `${Math.max(0, Math.min(100, number)).toFixed(1)}%` : "--";
}

function fmtLoosePercent(value: any): string {
  const number = Number(value);
  return Number.isFinite(number) ? `${Math.max(0, number).toFixed(1)}%` : "--";
}

function fmtBytesRate(value: any): string {
  const bytes = Number(value);
  if (!Number.isFinite(bytes) || bytes <= 0) return "0 B/s";
  return `${fmtBytes(bytes)}/s`;
}

function asNumber(value: any, fallback = 0): number {
  const number = Number(value);
  return Number.isFinite(number) ? number : fallback;
}

function isPendingTask(task: any): boolean {
  return ["queued", "dispatched", "running"].includes(String(task?.status || "").toLowerCase());
}

function fmtRelativeAge(value: any): string {
  if (!value) return "--";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "--";
  return fmtDuration(Math.max(0, Math.floor((Date.now() - date.getTime()) / 1000)));
}

function timeMs(value: any): number | null {
  if (!value) return null;
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? null : date.getTime();
}

function taskElapsedSeconds(task: any): number | null {
  const started = timeMs(task?.createdAt);
  if (started === null) return null;
  const terminal = ["succeeded", "failed"].includes(String(task?.status || "").toLowerCase());
  const ended = terminal ? timeMs(task?.updatedAt) : Date.now();
  if (ended === null) return null;
  return Math.max(0, (ended - started) / 1000);
}

function taskFailureReason(task: any): string {
  if (String(task?.status || "").toLowerCase() !== "failed") return "";
  const result = task?.result;
  if (typeof result === "string") return result;
  if (result && typeof result === "object" && !Array.isArray(result)) {
    const record = result as AnyRecord;
    for (const key of ["error", "reason", "message", "stderr", "detail"]) {
      if (typeof record[key] === "string" && record[key].length > 0) return record[key];
    }
  }
  return "任务失败但 provider 未返回明确原因";
}

function summarizeValue(value: any): string {
  if (value === null || value === undefined) return "--";
  if (typeof value === "boolean") return value ? "是" : "否";
  if (typeof value === "number") return String(value);
  if (typeof value === "string") return value.length > 80 ? `${value.slice(0, 77)}...` : value;
  if (Array.isArray(value)) return `${value.length} 项`;
  if (typeof value === "object") return `${Object.keys(value).length} 字段`;
  return String(value);
}

function summarizeFieldValue(key: string, value: any): string {
  const normalizedKey = key.replace(/[-_\s]/g, "").toLowerCase();
  const looksLikeTimeKey = normalizedKey === "ts" || normalizedKey.endsWith("at") || normalizedKey.endsWith("timestamp") || normalizedKey.endsWith("heartbeat");
  if ((typeof value === "string" || typeof value === "number") && looksLikeTimeKey) {
    const formatted = fmtDate(value);
    if (formatted !== "--") return formatted;
  }
  if (key === "bodyText" && typeof value === "string") {
    const kind = /^\s*[{[]/.test(value) ? "JSON" : "HTTP";
    return `${kind} body ${value.length} chars`;
  }
  return summarizeValue(value);
}

function objectEntries(value: any): Array<[string, any]> {
  if (!value || typeof value !== "object" || Array.isArray(value)) return [];
  return Object.entries(value);
}

function safeId(value: any): string {
  return String(value).replace(/[^a-zA-Z0-9_-]/g, "_");
}

function recordValue(data: any, key: string): any {
  return data && typeof data === "object" && !Array.isArray(data) ? data[key] : undefined;
}

function labelString(node: any, key: string, fallback = "未知"): string {
  const value = recordValue(node?.labels, key);
  return typeof value === "string" && value.length > 0 ? value : fallback;
}

function nodeGatewayVersion(node: any): string {
  return labelString(node, "providerGatewayVersion");
}

function nodeGatewayPolicy(node: any): string {
  return labelString(node, "providerGatewayUpgradePolicy");
}

function nodeGatewayStartedAt(node: any): string {
  return labelString(node, "providerGatewayStartedAt", "");
}

function nodeCapabilities(node: any): string[] {
  const value = recordValue(node?.labels, "unideskCapabilities");
  if (typeof value === "string") return value.split(",").map((item) => item.trim()).filter(Boolean);
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
}

function nodeHasCapability(node: any, capability: string): boolean {
  return nodeCapabilities(node).includes(capability);
}

function labelBoolean(node: any, key: string): boolean {
  const value = recordValue(node?.labels, key);
  return value === true || value === "true" || value === "1";
}

function nodeSshAvailability(node: any): { tone: string; label: string; detail: string } {
  if (!nodeHasCapability(node, "host.ssh")) return { tone: "fail", label: "不可用", detail: "未声明 host.ssh" };
  if (!labelBoolean(node, "hostSshConfigured")) return { tone: "warn", label: "未配置", detail: "缺少 SSH 环境变量" };
  if (!labelBoolean(node, "hostSshKeyPresent")) return { tone: "warn", label: "缺 key", detail: "私钥未挂载" };
  return { tone: "ok", label: "可用", detail: labelString(node, "hostSshTarget", "host.ssh ready") };
}

function nodeUpgradeAvailability(node: any): { tone: string; label: string; detail: string } {
  if (!nodeHasCapability(node, "provider.upgrade")) return { tone: "fail", label: "不可用", detail: "未声明 provider.upgrade" };
  const policy = nodeGatewayPolicy(node);
  if (policy !== "always-enabled") return { tone: "warn", label: "待确认", detail: `策略 ${policy}` };
  return { tone: "ok", label: "可用", detail: "always-enabled" };
}

function fmtGatewayVersion(value: any): string {
  const text = typeof value === "string" && value.length > 0 ? value : "未知";
  if (text === "未知") return "版本未知";
  return text.startsWith("v") ? text : `v${text}`;
}

function taskPayload(task: any): AnyRecord {
  return task?.payload && typeof task.payload === "object" && !Array.isArray(task.payload) ? task.payload as AnyRecord : {};
}

function taskResult(task: any): AnyRecord {
  return task?.result && typeof task.result === "object" && !Array.isArray(task.result) ? task.result as AnyRecord : {};
}

function taskUpgradeMode(task: any): string {
  const payload = taskPayload(task);
  const result = taskResult(task);
  const mode = payload.mode ?? result.mode;
  return mode === "schedule" ? "schedule" : "plan";
}

function taskUpgradeSource(task: any): string {
  const source = taskPayload(task).source;
  return typeof source === "string" && source.length > 0 ? source : "unknown";
}

function taskUpgradePolicy(task: any): string {
  const result = taskResult(task);
  const plan = result.plan && typeof result.plan === "object" && !Array.isArray(result.plan) ? result.plan as AnyRecord : {};
  const policy = result.policy ?? plan.policy;
  return typeof policy === "string" && policy.length > 0 ? policy : "--";
}

function taskUpgradeVersion(task: any): string {
  const result = taskResult(task);
  const plan = result.plan && typeof result.plan === "object" && !Array.isArray(result.plan) ? result.plan as AnyRecord : {};
  const value = result.targetProviderGatewayVersion
    ?? result.providerGatewayVersion
    ?? plan.targetProviderGatewayVersion
    ?? plan.providerGatewayVersion;
  return typeof value === "string" && value.length > 0 ? fmtGatewayVersion(value) : "版本未知";
}

function taskUpgradeOutcome(task: any): string {
  const status = String(task?.status || "").toLowerCase();
  if (status === "failed") return taskFailureReason(task);
  if (isPendingTask(task)) return "等待 provider 回传升级终态";
  const result = taskResult(task);
  if (typeof result.updaterContainerId === "string" && result.updaterContainerId.length > 0) return `updater ${result.updaterContainerId.slice(0, 18)}`;
  if (typeof result.message === "string" && result.message.length > 0) return result.message;
  if (result.plan) return "升级计划已生成";
  return "无升级结果摘要";
}

function providerUpgradeTasks(tasks: any[], providerId: string): any[] {
  return tasks
    .filter((task) => task?.providerId === providerId && task?.command === "provider.upgrade")
    .sort((left, right) => (timeMs(right.updatedAt) ?? 0) - (timeMs(left.updatedAt) ?? 0));
}

function latestScheduledUpgradeTask(records: any[]): any | null {
  return records.find((task) => taskUpgradeMode(task) === "schedule") || records[0] || null;
}

function microserviceRuntime(service: any): AnyRecord {
  return service?.runtime && typeof service.runtime === "object" && !Array.isArray(service.runtime) ? service.runtime : {};
}

function microserviceBackend(service: any): AnyRecord {
  return service?.backend && typeof service.backend === "object" && !Array.isArray(service.backend) ? service.backend : {};
}

function microserviceRepository(service: any): AnyRecord {
  return service?.repository && typeof service.repository === "object" && !Array.isArray(service.repository) ? service.repository : {};
}

function StatusBadge({ status, children }: AnyRecord) {
  const normalized = String(status || "unknown").toLowerCase();
  return h("span", { className: `status-badge ${normalized}` }, children || status || "unknown");
}

function MetricCard({ label, value, hint, tone, onClick, testId }: AnyRecord) {
  const interactive = typeof onClick === "function";
  return h("article", {
    className: `metric-card ${tone || ""} ${interactive ? "clickable" : ""}`,
    role: interactive ? "button" : undefined,
    tabIndex: interactive ? 0 : undefined,
    "data-testid": testId,
    onClick,
    onKeyDown: interactive ? (event: any) => {
      if (event.key === "Enter" || event.key === " ") {
        event.preventDefault();
        onClick();
      }
    } : undefined,
  },
    h("div", { className: "metric-label" }, label),
    h("div", { className: "metric-value" }, value),
    h("div", { className: "metric-hint" }, hint),
  );
}

function Panel({ title, eyebrow, actions, children, className, loading }: AnyRecord) {
  const contextLoading = React.useContext(LoadingContext);
  const isLoading = Boolean(loading) || contextLoading;
  return h("section", { className: `panel ${className || ""}` },
    h("div", { className: "panel-head" },
      h("div", null,
        eyebrow ? h("p", { className: "panel-eyebrow" }, eyebrow) : null,
        h(LoadingTitle, { title, loading: isLoading }),
      ),
      actions ? h("div", { className: "panel-actions" }, actions) : null,
    ),
    h("div", { className: "panel-body" }, children),
  );
}

function RawButton({ title, data, onOpen, testId }: AnyRecord) {
  const [loading, setLoading] = useState(false);
  const loadData = data && typeof data === "object" && typeof data._loadRaw === "function" ? data._loadRaw : null;
  async function open(): Promise<void> {
    if (!loadData) {
      onOpen(title, data);
      return;
    }
    setLoading(true);
    try {
      onOpen(title, await loadData());
    } catch (err) {
      onOpen(title, { ok: false, error: errorMessage(err, "读取原始 JSON 失败"), fallback: data });
    } finally {
      setLoading(false);
    }
  }
  return h("button", {
    type: "button",
    className: "ghost-btn",
    "data-testid": testId,
    disabled: loading,
    onClick: () => void open(),
  }, loading ? "读取中" : "查看原始JSON");
}

function RawDialog({ raw, onClose }: AnyRecord) {
  if (!raw) return null;
  return h("div", { className: "modal-backdrop", role: "presentation" },
    h("section", { className: "raw-dialog", role: "dialog", "aria-modal": "true", "aria-label": raw.title },
      h("div", { className: "raw-dialog-head" },
        h("h2", null, raw.title),
        h("button", { type: "button", className: "ghost-btn", onClick: onClose }, "关闭"),
      ),
      h("pre", { className: "raw-json", "data-testid": "raw-json" }, JSON.stringify(raw.data, null, 2)),
    ),
  );
}

function LabelChips({ labels, limit = 8 }: AnyRecord) {
  const entries = objectEntries(labels).slice(0, limit);
  if (entries.length === 0) return h("span", { className: "muted" }, "无标签");
  return h("div", { className: "chip-row" },
    entries.map(([key, value]) => h("span", { key, className: "data-chip" },
      h("b", null, key),
      h("span", null, summarizeValue(value)),
    )),
  );
}

function GatewayVersionBadge({ node }: AnyRecord) {
  const version = nodeGatewayVersion(node);
  return h("span", {
    className: `version-chip ${version === "未知" ? "unknown" : ""}`,
    "data-testid": `gateway-version-${safeId(node?.providerId || "unknown")}`,
  }, fmtGatewayVersion(version));
}

function CapabilityBadge({ title, state, testId }: AnyRecord) {
  return h("span", {
    className: `capability-badge ${state.tone}`,
    title: state.detail,
    "data-testid": testId,
  },
    h("b", null, title),
    h("strong", null, state.label),
    h("small", null, state.detail),
  );
}

function NodeAvailabilityStrip({ node }: AnyRecord) {
  const providerId = safeId(node?.providerId || "unknown");
  return h("div", { className: "node-availability-strip" },
    h(CapabilityBadge, { title: "SSH 透传", state: nodeSshAvailability(node), testId: `ssh-availability-${providerId}` }),
    h(CapabilityBadge, { title: "远程更新", state: nodeUpgradeAvailability(node), testId: `upgrade-availability-${providerId}` }),
  );
}

function DataSummary({ data, empty = "无数据" }: AnyRecord) {
  if (data === null || data === undefined) return h("span", { className: "muted" }, empty);
  if (typeof data !== "object") return h("span", { className: "summary-value" }, summarizeValue(data));
  if (Array.isArray(data)) return h("span", { className: "summary-value" }, `${data.length} 项列表`);
  const entries = Object.entries(data).slice(0, 5);
  if (entries.length === 0) return h("span", { className: "muted" }, empty);
  return h("div", { className: "summary-grid" }, entries.map(([key, value]) =>
    h("span", { key, className: "summary-item" }, h("b", null, key), h("span", null, summarizeFieldValue(key, value))),
  ));
}

function EmptyState({ title, text }: AnyRecord) {
  return h("div", { className: "empty-state" }, h("strong", null, title), h("span", null, text));
}

function LoginScreen({ onLogin }: AnyRecord) {
  const [username, setUsername] = useState(cfg.authUsername || "admin");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);

  async function submit(event: any) {
    event.preventDefault();
    setBusy(true);
    setError("");
    try {
      const session = await requestJson("/login", { method: "POST", body: JSON.stringify({ username, password }) });
      onLogin(session);
    } catch (err) {
      setError(errorMessage(err, "登录失败"));
    } finally {
      setBusy(false);
    }
  }

  return h("main", { className: "login-screen", "data-testid": "login-screen" },
    h("section", { className: "login-card" },
      h("div", { className: "login-brand" }, h("span", { className: "brand-mark" }, "UD"), h("div", null, h("h1", null, "UniDesk"), h("p", null, "Control Plane Login"))),
      h("form", { className: "login-form", onSubmit: submit },
        h("label", null, "账号", h("input", { name: "username", autoComplete: "username", value: username, onChange: (event: any) => setUsername(event.target.value) })),
        h("label", null, "密码", h("input", { name: "password", type: "password", autoComplete: "current-password", value: password, onChange: (event: any) => setPassword(event.target.value) })),
        h(UniDeskErrorBanner, { error }),
        h("button", { type: "submit", disabled: busy }, busy ? "登录中" : "登录"),
      ),
      h("div", { className: "login-note" }, "默认账号由 config.json 注入；公网入口只暴露前端登录面。"),
    ),
  );
}

function TopBar({ connection, lastRefresh, onRefresh, onLogout, session, clock, activeStatusItems = [], onNotificationToggle, unreadCount = 0, environment = {} }: AnyRecord) {
  const devMode = isDevEnvironment(environment);
  const statusItems = [
    ...(devMode ? [{ key: "environment", label: "环境", value: `${environment.namespace || "unidesk-dev"}`, tone: "warn" }] : []),
    { key: "core", label: "核心", value: connection.text, tone: connection.ok ? "ok" : "fail", testId: "conn-text" },
    ...(Array.isArray(activeStatusItems) ? activeStatusItems : []),
    { key: "refresh", label: "刷新", value: lastRefresh ? fmtClock(lastRefresh) : "未刷新" },
    { key: "clock", label: displayTimeLabel(), value: fmtClock(clock) },
    { key: "user", label: "用户", value: session?.user?.username || "--", tone: "user" },
  ];
  return h("header", { className: "topbar" },
    h("div", null,
      h("p", { className: "eyebrow" }, "Distributed Work Platform"),
      h("h1", null, "UniDesk 控制平面"),
      devMode ? h("div", { className: "dev-env-ribbon", "data-testid": "dev-environment-ribbon" },
        h("b", null, "DEV"),
        h("span", null, environment.namespace || "unidesk-dev"),
        h("span", null, environment.deployRef || "origin/master:deploy.json#environments.dev"),
        h("span", null, shortCommit(environment.commit || environment.requestedCommit)),
      ) : null,
    ),
    h(TopStatusBar, {
      className: "global-top-status",
      title: "状态",
      items: statusItems,
      actions: [
        h("button", {
          key: "notification",
          type: "button",
          className: `notification-icon-btn ${unreadCount > 0 ? "has-unread" : ""}`,
          onClick: onNotificationToggle,
          "aria-label": "通知",
        },
          "🔔",
          unreadCount > 0 ? h("span", { key: "badge", className: "notification-badge" }, unreadCount > 99 ? "99+" : unreadCount) : null
        ),
        h("button", { key: "refresh", type: "button", className: "ghost-btn", onClick: onRefresh }, "刷新"),
        h("button", { key: "logout", type: "button", className: "ghost-btn danger", onClick: onLogout }, "退出"),
      ],
    }),
  );
}

type NavigateHandler = (moduleId: string, tabId: string, historyMode?: "push" | "replace") => void;

interface RouteAnchorProps {
  moduleId: string;
  tabId: string;
  className: string;
  active?: boolean;
  title?: string;
  testId?: string;
  onNavigate: NavigateHandler;
  children?: React.ReactNode;
}

function shouldHandleSpaRouteClick(event: React.MouseEvent<HTMLAnchorElement>): boolean {
  return !event.defaultPrevented
    && event.button === 0
    && !event.metaKey
    && !event.altKey
    && !event.ctrlKey
    && !event.shiftKey
    && event.currentTarget.target !== "_blank";
}

function RouteAnchor({ moduleId, tabId, className, active = false, title, testId, onNavigate, children }: RouteAnchorProps) {
  const route = pathForTarget(ROUTE_REGISTRY, moduleId, tabId);
  return h("a", {
    href: route,
    role: "button",
    className,
    title,
    "aria-current": active ? "page" : undefined,
    "data-testid": testId,
    "data-route": route,
    onClick: (event: React.MouseEvent<HTMLAnchorElement>) => {
      if (!shouldHandleSpaRouteClick(event)) return;
      event.preventDefault();
      onNavigate(moduleId, tabId);
    },
  }, children);
}

function Sidebar({ activeModule, activeTabs, onNavigate, collapsed, onToggle }: AnyRecord) {
  return h("aside", { className: `rail ${collapsed ? "collapsed" : ""}`, "aria-label": "主模块" },
    h("div", { className: "brand" },
      h("span", { className: "brand-mark" }, "UD"),
      h("span", { className: "brand-text" }, "UniDesk"),
      h("button", { type: "button", className: "rail-toggle", onClick: onToggle, "aria-label": collapsed ? "展开左侧边栏" : "收起左侧边栏", "data-testid": "rail-toggle" }, collapsed ? "»" : "«"),
    ),
    MODULES.map((module: any) => {
      const tabId = activeTabs[module.id] || DEFAULT_ACTIVE_TABS[module.id] || module.tabs[0]?.id || "";
      return h(RouteAnchor, {
        key: module.id,
        moduleId: module.id,
        tabId,
        className: `module ${activeModule === module.id ? "active" : ""}`,
        active: activeModule === module.id,
        title: module.label,
        onNavigate,
      }, h("span", { className: "module-code" }, module.code), h("span", null, module.label));
    }),
  );
}

function TabBar({ module, activeTab, onNavigate }: AnyRecord) {
  return h("nav", { className: "tabs", "aria-label": `${module.label} 子功能` },
    module.tabs.map((tab: any) => h(RouteAnchor, {
      key: tab.id,
      moduleId: module.id,
      tabId: tab.id,
      className: `tab ${activeTab === tab.id ? "active" : ""}`,
      active: activeTab === tab.id,
      onNavigate,
    }, tab.label)),
  );
}

function OverviewPage({ data, onRaw, onNavigate }: AnyRecord) {
  const overview = data.overview || {};
  const onlineNodes = data.nodes.filter((node: any) => node.status === "online");
  const pendingTasks = data.pendingTasks || data.tasks.filter(isPendingTask);
  const pendingCount = overview.pendingTaskCount ?? pendingTasks.length;
  const recentTasks = data.tasks.slice(0, 5);
  const pgdata = overview.pgdata || {};
  const microserviceAvailability = overview.microserviceAvailability || {};
  const microserviceTotal = asNumber(microserviceAvailability.totalCount);
  const microserviceHealthy = asNumber(microserviceAvailability.healthyCount);
  const microserviceUnhealthy = asNumber(microserviceAvailability.unhealthyCount);
  return h("div", { className: "page-grid overview-grid", "data-testid": "overview-page" },
    h(Panel, { title: "核心指标", eyebrow: "Control" },
      h("div", { className: "metric-grid" },
        h(MetricCard, { label: "数据库", value: overview.dbReady ? "READY" : "WAIT", hint: "PostgreSQL internal network", tone: overview.dbReady ? "ok" : "warn" }),
        h(MetricCard, { label: "PGDATA", value: fmtBytes(pgdata.databaseBytes), hint: `${pgdata.volumeName || "unidesk_pgdata_10gb"} / ${pgdata.databasePretty || "--"} / budget ${pgdata.volumeSize || "--"}`, tone: "ok", testId: "pgdata-usage-card" }),
        h(MetricCard, { label: "在线节点", value: overview.onlineNodeCount ?? 0, hint: `${overview.nodeCount ?? 0} registered`, tone: "ok" }),
        h(MetricCard, { label: "WebSocket", value: overview.activeSocketCount ?? 0, hint: "Provider ingress sockets" }),
        h(MetricCard, { label: "用户服务可用", value: microserviceTotal > 0 ? `${microserviceHealthy}/${microserviceTotal}` : "--", hint: microserviceTotal > 0 ? `healthyCount ${microserviceHealthy} · unhealthyCount ${microserviceUnhealthy}` : "strict /health probes", tone: microserviceTotal > 0 && microserviceUnhealthy === 0 ? "ok" : "warn", testId: "microservice-availability-card" }),
        h(MetricCard, { label: "待处理任务", value: pendingCount, hint: pendingCount > 0 ? "点击查看具体任务" : `timeout ${fmtDuration(Math.floor((overview.taskPendingTimeoutMs ?? 0) / 1000))}`, tone: pendingCount > 0 ? "warn" : "ok", onClick: () => onNavigate("tasks", "pending"), testId: "pending-task-card" }),
      ),
    ),
    h(Panel, { title: "本机 Provider", eyebrow: "Self Connected" },
      onlineNodes.length === 0 ? h(EmptyState, { title: "暂无在线节点", text: "provider-gateway 未完成自接入" }) :
        h("div", { className: "node-card-list" }, onlineNodes.slice(0, 4).map((node: any) => h(NodeCard, { key: node.providerId, node, onRaw }))),
    ),
    h(Panel, {
      title: "待处理任务明细",
      eyebrow: `${pendingCount} Pending`,
      actions: h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("tasks", "pending"), "data-testid": "pending-task-detail-link" }, "进入任务调度"),
    },
      pendingTasks.length === 0 ? h(EmptyState, { title: "当前无待处理", text: "queued / dispatched / running 超时后会自动转为 failed，避免总览长期卡住" }) :
        h("div", { className: "compact-list" }, pendingTasks.slice(0, 5).map((task: any) => h(TaskCompactRow, { key: task.id, task, onRaw }))),
    ),
    h(Panel, { title: "最近任务", eyebrow: "Dispatch" },
      recentTasks.length === 0 ? h(EmptyState, { title: "暂无任务", text: "可以在任务调度模块发起 docker.ps 或 echo" }) :
        h("div", { className: "compact-list" }, recentTasks.map((task: any) => h(TaskCompactRow, { key: task.id, task, onRaw }))),
    ),
  );
}

function NodeCard({ node, onRaw }: AnyRecord) {
  return h("article", { className: "node-card" },
    h("div", { className: "node-card-head" },
      h("div", null, h("strong", null, node.name), h("code", null, node.providerId)),
      h(StatusBadge, { status: node.status }),
    ),
    h("div", { className: "node-version-line" },
      h(GatewayVersionBadge, { node }),
      h("span", null, `升级策略 ${nodeGatewayPolicy(node)}`),
    ),
    h(NodeAvailabilityStrip, { node }),
    h(LabelChips, { labels: node.labels, limit: 6 }),
    h("div", { className: "node-card-foot" },
      h("span", null, `心跳 ${fmtDate(node.lastHeartbeat)}`),
      h(RawButton, { title: `Provider ${node.providerId}`, data: node, onOpen: onRaw, testId: `raw-node-${safeId(node.providerId)}` }),
    ),
  );
}

function EventsPage({ events, onRaw }: AnyRecord) {
  return h(Panel, { title: "事件摘要", eyebrow: "Latest 100" },
    events.length === 0 ? h(EmptyState, { title: "暂无事件", text: "Provider 注册、心跳超时和任务状态会写入事件流" }) :
      h("div", { className: "table-wrap" }, h("table", null,
        h("thead", null, h("tr", null, h("th", null, "ID"), h("th", null, "类型"), h("th", null, "来源"), h("th", null, "摘要"), h("th", null, "时间"), h("th", null, "操作"))),
        h("tbody", null, events.map((event: any) => h("tr", { key: event.id },
          h("td", null, h("code", null, event.id)),
          h("td", null, h(StatusBadge, { status: event.type }, event.type)),
          h("td", null, h("code", null, event.source)),
          h("td", null, h(DataSummary, { data: event.payload })),
          h("td", null, fmtDate(event.createdAt)),
          h("td", null, h(RawButton, { title: `Event ${event.id}`, data: event, onOpen: onRaw })),
        ))),
      )),
  );
}

function LogsPage({ logs, onRaw }: AnyRecord) {
  return h(Panel, { title: "服务日志", eyebrow: "Core Recent" },
    logs.length === 0 ? h(EmptyState, { title: "暂无日志", text: "backend-core 内存日志会在请求和 provider 事件后出现" }) :
      h("div", { className: "log-list" }, logs.slice(-80).reverse().map((log: any, index: any) => h("article", { key: index, className: `log-row ${log.level || "info"}` },
        h("span", null, fmtDate(log.ts)),
        h("b", null, log.level || "info"),
        h("strong", null, log.message || "log"),
        h(DataSummary, { data: log.data, empty: "无附加字段" }),
        h(RawButton, { title: `Log ${log.message || index}`, data: log, onOpen: onRaw }),
      ))),
  );
}

function NodeListPage({ nodes, onRaw }: AnyRecord) {
  return h(Panel, { title: "节点清单", eyebrow: `${nodes.length} Providers` },
    nodes.length === 0 ? h(EmptyState, { title: "暂无 Provider 节点", text: "确认 provider-gateway 已连接 provider ingress" }) :
      h("div", { className: "table-wrap" }, h("table", { className: "node-list-table" },
        h("thead", null, h("tr", null, h("th", null, "状态"), h("th", null, "Provider"), h("th", null, "网关版本"), h("th", null, "运维可用性"), h("th", null, "资源标签"), h("th", null, "连接时间"), h("th", null, "最后心跳"), h("th", null, "操作"))),
        h("tbody", null, nodes.map((node: any) => h("tr", { key: node.providerId },
          h("td", null, h(StatusBadge, { status: node.status })),
          h("td", null, h("strong", null, node.name), h("code", null, node.providerId)),
          h("td", null, h("div", { className: "gateway-cell" }, h(GatewayVersionBadge, { node }), h("span", null, nodeGatewayPolicy(node)))),
          h("td", null, h(NodeAvailabilityStrip, { node })),
          h("td", null, h(LabelChips, { labels: node.labels, limit: 5 })),
          h("td", null, fmtDate(node.connectedAt)),
          h("td", null, fmtDate(node.lastHeartbeat)),
          h("td", null, h(RawButton, { title: `Provider ${node.providerId}`, data: node, onOpen: onRaw, testId: `raw-node-table-${safeId(node.providerId)}` })),
        ))),
      )),
  );
}

function LabelsPage({ nodes }: AnyRecord) {
  const labels = useMemo(() => {
    const rows = [];
    for (const node of nodes) {
      for (const [key, value] of objectEntries(node.labels)) rows.push({ providerId: node.providerId, name: node.name, key, value });
    }
    return rows;
  }, [nodes]);
  return h(Panel, { title: "资源标签", eyebrow: "Structured Labels" },
    labels.length === 0 ? h(EmptyState, { title: "暂无标签", text: "provider-gateway 注册消息会同步资源标签" }) :
      h("div", { className: "label-matrix" }, labels.map((row: any) => h("article", { key: `${row.providerId}-${row.key}`, className: "label-card" },
        h("span", null, row.key),
        h("strong", null, summarizeValue(row.value)),
        h("code", null, row.providerId),
      ))),
  );
}

function HeartbeatPage({ nodes }: AnyRecord) {
  return h(Panel, { title: "心跳状态", eyebrow: "Provider Liveness" },
    nodes.length === 0 ? h(EmptyState, { title: "无心跳", text: "等待 provider 注册和 heartbeat" }) :
      h("div", { className: "heartbeat-list" }, nodes.map((node: any) => h("article", { key: node.providerId, className: "heartbeat-row" },
        h("span", { className: `pulse ${node.status}` }),
        h("div", null, h("strong", null, node.name), h("code", null, node.providerId)),
        h("div", null, h("span", null, "connected"), h("b", null, fmtDate(node.connectedAt))),
        h("div", null, h("span", null, "last heartbeat"), h("b", null, fmtDate(node.lastHeartbeat))),
      ))),
  );
}

function metricPointFromCurrent(current: AnyRecord): AnyRecord {
  const cpu = current?.cpu || {};
  const memory = current?.memory || {};
  const disk = current?.disk || {};
  return {
    at: current?.collectedAt,
    cpuPercent: asNumber(cpu.percent),
    memoryPercent: asNumber(memory.percent),
    diskPercent: asNumber(disk.percent),
    memoryUsedBytes: asNumber(memory.usedBytes),
    memoryTotalBytes: asNumber(memory.totalBytes),
    diskUsedBytes: asNumber(disk.usedBytes),
    diskTotalBytes: asNumber(disk.totalBytes),
    load1: asNumber(cpu.load1),
  };
}

function synchronizedMetricPoints(history: any[], current: AnyRecord | null): AnyRecord[] {
  if (!current) return [];
  const currentPoint = metricPointFromCurrent(current);
  const currentAt = timeMs(currentPoint.at);
  const points = (Array.isArray(history) ? history : [])
    .filter((point) => point && typeof point === "object")
    .filter((point) => currentAt === null || timeMs(point.at) !== currentAt);
  points.push(currentPoint);
  return points
    .sort((left, right) => (timeMs(left.at) ?? 0) - (timeMs(right.at) ?? 0))
    .slice(-60);
}

function NodeMonitorPage({ nodes, systemStatuses, tasks, onRaw, refresh }: AnyRecord) {
  const [selectedProvider, setSelectedProvider] = useState("");
  const merged = useMemo(() => nodes.map((node: any) => {
    const status = systemStatuses.find((item: any) => item.providerId === node.providerId);
    return {
      ...node,
      systemCurrent: status?.current || null,
      systemLastKnown: status?.lastKnown || null,
      systemCurrentCollectedAt: status?.currentCollectedAt || null,
      systemStale: Boolean(status?.stale),
      systemStaleSeconds: status?.staleSeconds ?? null,
      systemHistory: status?.history || [],
      systemUpdatedAt: status?.updatedAt || null,
    };
  }), [nodes, systemStatuses]);
  const active = merged.find((node: any) => node.providerId === selectedProvider) || merged[0] || null;
  useEffect(() => {
    if (!selectedProvider && merged[0]) setSelectedProvider(merged[0].providerId);
  }, [merged.length, selectedProvider]);

  if (!active) return h(EmptyState, { title: "暂无资源监控", text: "等待 provider 上报 CPU、内存和硬盘指标" });

  const current = active.systemCurrent;
  const history = active.systemHistory || [];
  const cpu = current?.cpu || {};
  const memory = current?.memory || {};
  const disk = current?.disk || {};
  const points = synchronizedMetricPoints(history, current);
  const staleText = active.systemCurrentCollectedAt
    ? `最后采样 ${fmtDate(active.systemCurrentCollectedAt)}，已过期 ${fmtDuration(asNumber(active.systemStaleSeconds))}`
    : "最后采样时间不可用";

  return h("div", { className: "monitor-page", "data-testid": "node-monitor-page" },
    h("div", { className: "docker-node-strip" },
      merged.map((node: any) => h("button", {
        key: node.providerId,
        type: "button",
        className: `docker-node-tile ${active.providerId === node.providerId ? "active" : ""}`,
        onClick: () => setSelectedProvider(node.providerId),
      },
        h("span", { className: `pulse ${node.status}` }),
        h("strong", null, node.name),
        h("code", null, node.providerId),
        h("span", null, node.systemCurrent ? `CPU ${fmtPercent(node.systemCurrent.cpu?.percent)} / MEM ${fmtPercent(node.systemCurrent.memory?.percent)}` : node.systemStale ? "指标过期" : "等待指标"),
      )),
    ),
    h("div", { className: "monitor-layout" },
      h(Panel, {
        title: "任务管理器视图",
        eyebrow: active.name,
        className: "monitor-main-panel",
        actions: current || active.systemStale ? h(RawButton, { title: `System ${active.providerId}`, data: { current, lastKnown: active.systemLastKnown, currentCollectedAt: active.systemCurrentCollectedAt, stale: active.systemStale, staleSeconds: active.systemStaleSeconds, history }, onOpen: onRaw }) : null,
      },
        !current ? h(EmptyState, { title: active.systemStale ? "系统指标已过期" : "系统指标未上报", text: active.systemStale ? `${staleText}；等待 provider-gateway 恢复 system.status 上报` : "provider-gateway 会周期性采集 /proc 与 df，并保存历史曲线" }) :
          h("div", null,
            h("div", { className: "monitor-hero" },
              h("div", null,
                h("p", { className: "panel-eyebrow" }, "Node Performance"),
                h("h3", null, active.name),
                h("div", { className: "docker-meta" },
                  h("span", null, `${cpu.cores || 0} CPU cores`),
                  h("span", null, `load ${asNumber(cpu.load1).toFixed(2)} / ${asNumber(cpu.load5).toFixed(2)} / ${asNumber(cpu.load15).toFixed(2)}`),
                  h("span", null, `memory actual ${fmtBytes(memory.usedBytes)} / ${fmtBytes(memory.totalBytes)}`),
                  h("span", null, `disk ${fmtBytes(disk.usedBytes)} / ${fmtBytes(disk.totalBytes)}`),
                ),
              ),
              h(StatusBadge, { status: current.ok ? "online" : "warn" }, current.ok ? "METRICS READY" : "METRICS DEGRADED"),
            ),
            h("div", { className: "monitor-chart-grid" },
              h(MetricChart, { title: "CPU", metricKey: "cpuPercent", current: cpu.percent, points, detail: `${cpu.cores || 0} cores / load ${asNumber(cpu.load1).toFixed(2)}`, tone: "cpu", testId: "metric-chart-cpu" }),
              h(MetricChart, { title: "Memory", metricKey: "memoryPercent", current: memory.percent, points, detail: `${fmtBytes(memory.usedBytes)} actual / ${fmtBytes(memory.cacheBytes)} cache excluded`, tone: "memory", testId: "metric-chart-memory" }),
              h(MetricChart, { title: "Disk", metricKey: "diskPercent", current: disk.percent, points, detail: `${disk.path || "/"} mounted ${disk.mount || "--"}`, tone: "disk", testId: "metric-chart-disk" }),
            ),
            h("div", { className: "monitor-summary-grid" },
              h(MetricCard, { label: "CPU 当前", value: fmtPercent(cpu.percent), hint: `history ${points.length} samples`, tone: "ok" }),
              h(MetricCard, { label: "实际内存", value: fmtBytes(memory.usedBytes), hint: `${fmtPercent(memory.percent)} 不含缓存` }),
              h(MetricCard, { label: "硬盘已用", value: fmtBytes(disk.usedBytes), hint: fmtPercent(disk.percent) }),
              h(MetricCard, { label: "更新时间", value: fmtDate(current.collectedAt || active.systemUpdatedAt), hint: active.providerId }),
            ),
            h(ProcessResourceTable, { current, onRaw }),
          ),
      ),
      h("div", { className: "monitor-side-stack" },
        h(UpgradeControl, { provider: active, refresh, onRaw }),
        h(ProviderUpgradeRecordsPanel, { provider: active, tasks, onRaw, limit: 5 }),
        h(Panel, { title: "采样说明", eyebrow: "Retention" },
          h("div", { className: "monitor-note-list" },
            h("article", null, h("b", null, "CPU"), h("span", null, "从 /proc/stat 计算相邻采样差值，首个采样用 load/cores 近似")),
            h("article", null, h("b", null, "Memory"), h("span", null, "实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem，不把 page cache / buffer 计入占用")),
            h("article", null, h("b", null, "Disk"), h("span", null, "使用 df -PB1 对配置路径采样，默认监控根文件系统")),
            h("article", null, h("b", null, "Process"), h("span", null, "从 /proc/[pid] 采集进程 CPU、实际内存 PSS、RSS、线程数和磁盘 I/O 速率；PSS 不重复计算共享内存，表格默认按内存占用降序")),
          ),
        ),
      ),
    ),
  );
}

type ProcessSortKey = "memory" | "cpu" | "disk" | "pid" | "name" | "user" | "threads" | "runtime";

function processMemoryBytes(row: AnyRecord): number {
  return asNumber(row.memoryBytes, asNumber(row.pssBytes, asNumber(row.rssBytes)));
}

function processSortValue(row: AnyRecord, key: ProcessSortKey): string | number {
  if (key === "memory") return processMemoryBytes(row);
  if (key === "cpu") return asNumber(row.cpuPercent);
  if (key === "disk") return asNumber(row.readBytesPerSecond) + asNumber(row.writeBytesPerSecond);
  if (key === "pid") return asNumber(row.pid);
  if (key === "threads") return asNumber(row.threads);
  if (key === "runtime") return asNumber(row.elapsedSeconds);
  if (key === "user") return String(row.user || "");
  return String(row.name || row.command || "");
}

function ProcessMeter({ value, label, tone }: AnyRecord) {
  const width = Math.max(1, Math.min(100, asNumber(value)));
  return h("div", { className: `process-meter ${tone || ""}` },
    h("span", { style: { width: `${width}%` } }),
    h("b", null, label),
  );
}

function ProcessResourceTable({ current, onRaw }: AnyRecord) {
  const [sort, setSort] = useState({ key: "memory", direction: "desc" });
  const contextLoading = React.useContext(LoadingContext);
  const processSummary = current?.processSummary && typeof current.processSummary === "object" ? current.processSummary : {};
  const processes = Array.isArray(current?.processes) ? current.processes : [];
  const memoryMode = String(processSummary.memoryMode || "");
  const memoryModeLabel = memoryMode.includes("pss_smaps_rollup")
    ? "PSS"
    : memoryMode === "rss_minus_shared_fallback"
      ? "RSS-shared"
      : "RSS fallback";
  const rows = useMemo(() => {
    const direction = sort.direction === "asc" ? 1 : -1;
    return [...processes].sort((left: AnyRecord, right: AnyRecord) => {
      const a = processSortValue(left, sort.key);
      const b = processSortValue(right, sort.key);
      if (typeof a === "string" || typeof b === "string") return String(a).localeCompare(String(b), "zh-CN") * direction;
      return (a - b) * direction || asNumber(left.pid) - asNumber(right.pid);
    });
  }, [processes, sort.key, sort.direction]);

  const sortHeader = (label: string, key: ProcessSortKey) => {
    const active = sort.key === key;
    const ariaSort = active ? (sort.direction === "asc" ? "ascending" : "descending") : "none";
    return h("th", { "aria-sort": ariaSort },
      h("button", {
        type: "button",
        className: `process-sort-button ${active ? "active" : ""}`,
        "data-testid": `process-sort-${key}`,
        onClick: () => setSort((previous: AnyRecord) => ({
          key,
          direction: previous.key === key && previous.direction === "desc" ? "asc" : "desc",
        })),
      }, label, h("span", null, active ? (sort.direction === "desc" ? "↓" : "↑") : "↕")),
    );
  };

  return h("section", { className: "process-resource-panel", "data-testid": "process-resource-panel" },
    h("div", { className: "process-resource-head" },
      h("div", null,
        h("p", { className: "panel-eyebrow" }, "Windows Resource Monitor Style"),
        h(LoadingTitle, { title: "进程资源占用", level: 3, loading: contextLoading }),
      ),
      h("div", { className: "process-resource-actions" },
        h("span", { className: "data-chip" }, "默认按内存排序"),
        h("span", { className: "data-chip" }, `内存口径 ${memoryModeLabel}`),
        h("span", { className: "data-chip" }, `${asNumber(processSummary.visible, rows.length)} / ${asNumber(processSummary.total, rows.length)} 进程`),
        h(RawButton, { title: "Process Resource Snapshot", data: { processSummary, processes }, onOpen: onRaw, testId: "raw-process-resources" }),
      ),
    ),
    rows.length === 0 ? h(EmptyState, { title: "暂无进程资源数据", text: "等待 provider-gateway 上报 /proc/[pid] 采样；旧版 provider 需要先升级到支持进程资源表的版本" }) :
      h("div", { className: "process-table-wrap" },
        h("table", { className: "process-resource-table", "data-testid": "process-resource-table" },
          h("thead", null, h("tr", null,
            sortHeader("进程", "name"),
            sortHeader("PID", "pid"),
            sortHeader("用户", "user"),
            h("th", null, "状态"),
            sortHeader("CPU", "cpu"),
            sortHeader("内存", "memory"),
            h("th", null, "PSS / RSS"),
            sortHeader("磁盘 I/O", "disk"),
            sortHeader("线程", "threads"),
            sortHeader("运行时长", "runtime"),
          )),
          h("tbody", null, rows.map((row: AnyRecord) => {
            const diskRate = asNumber(row.readBytesPerSecond) + asNumber(row.writeBytesPerSecond);
            const memoryBytes = processMemoryBytes(row);
            return h("tr", {
              key: `${row.pid}-${row.startedAt}`,
              "data-testid": `process-row-${safeId(row.pid)}`,
              "data-memory-bytes": String(memoryBytes),
              "data-cpu-percent": String(asNumber(row.cpuPercent)),
              "data-disk-bps": String(diskRate),
              "data-pid": String(asNumber(row.pid)),
            },
              h("td", null,
                h("div", { className: "process-name-cell" },
                  h("strong", null, row.name || "--"),
                  h("span", { className: "process-command" }, row.command || "--"),
                ),
              ),
              h("td", null, h("code", null, row.pid || "--")),
              h("td", null, row.user || `uid:${row.uid ?? "--"}`),
              h("td", null, h("span", { className: `process-state state-${safeId(row.state || "unknown")}` }, row.state || "?")),
              h("td", null, h(ProcessMeter, { value: row.cpuPercent, label: fmtLoosePercent(row.cpuPercent), tone: "cpu" })),
              h("td", null, h(ProcessMeter, { value: row.memoryPercent, label: fmtPercent(row.memoryPercent), tone: "memory" })),
              h("td", null,
                h("div", { className: "process-io-cell" },
                  h("strong", null, fmtBytes(memoryBytes)),
                  h("span", null, `RSS ${fmtBytes(row.rssBytes)}`),
                ),
              ),
              h("td", null, h("div", { className: "process-io-cell" },
                h("strong", null, fmtBytesRate(diskRate)),
                h("span", null, `R ${fmtBytesRate(row.readBytesPerSecond)} / W ${fmtBytesRate(row.writeBytesPerSecond)}`),
              )),
              h("td", null, row.threads || 0),
              h("td", null, fmtDuration(asNumber(row.elapsedSeconds))),
            );
          })),
        ),
      ),
  );
}

function MetricChart({ title, metricKey, current, points, detail, tone, testId }: AnyRecord) {
  const values = points.map((point: any) => Math.max(0, Math.min(100, asNumber(point[metricKey]))));
  const chartValues = values.length > 1 ? values : [values[0] || 0, values[0] || 0];
  const step = chartValues.length <= 1 ? 100 : 100 / (chartValues.length - 1);
  const linePoints = chartValues.map((value: any, index: any) => `${(index * step).toFixed(2)},${(46 - value * 0.42).toFixed(2)}`).join(" ");
  const areaPoints = `0,48 ${linePoints} 100,48`;
  return h("article", { className: `metric-chart ${tone}`, "data-testid": testId },
    h("div", { className: "metric-chart-head" },
      h("div", null, h("span", null, title), h("strong", null, fmtPercent(current))),
      h("code", null, `${points.length} pts`),
    ),
    h("svg", { viewBox: "0 0 100 48", preserveAspectRatio: "none", role: "img", "aria-label": `${title} usage curve` },
      h("polygon", { points: areaPoints }),
      h("polyline", { points: linePoints }),
      h("line", { x1: "0", x2: "100", y1: "24", y2: "24" }),
    ),
    h("div", { className: "metric-chart-foot" }, h("span", null, "0%"), h("span", null, detail), h("span", null, "100%")),
  );
}

function asArray(value: any): any[] {
  return Array.isArray(value) ? value : [];
}

function summaryRows(snapshot: any): any[] {
  const core = asArray(snapshot?.core?.requests?.componentSummary);
  const frontend = asArray(snapshot?.frontend?.requests?.componentSummary);
  return [...frontend, ...core].sort((left, right) => asNumber(right.requestCount) - asNumber(left.requestCount));
}

function operationRows(snapshot: any): any[] {
  const core = asArray(snapshot?.core?.operations?.summary);
  const frontend = asArray(snapshot?.frontend?.operations?.summary);
  return [...frontend, ...core].sort((left, right) => asNumber(right.count) - asNumber(left.count));
}

function failureRows(snapshot: any): any[] {
  const core = asArray(snapshot?.core?.requests?.recentFailures).map((row: any) => ({ source: "backend", ...row }));
  const frontend = asArray(snapshot?.frontend?.requests?.recentFailures).map((row: any) => ({ source: "frontend", ...row }));
  return [...frontend, ...core].sort((left, right) => (timeMs(right.at) ?? 0) - (timeMs(left.at) ?? 0)).slice(0, 20);
}

function slowOperationRows(snapshot: any): any[] {
  const core = asArray(snapshot?.core?.operations?.recentSlowOperations);
  const frontend = asArray(snapshot?.frontend?.operations?.recentSlowOperations);
  return [...frontend, ...core].sort((left, right) => asNumber(right.durationMs) - asNumber(left.durationMs)).slice(0, 20);
}

function browserMemoryBytes(frontendPerformance: any): number {
  const memory = (performance as any).memory;
  const used = Number(memory?.usedJSHeapSize);
  if (Number.isFinite(used) && used > 0) return used;
  const bundleBytes = Number(frontendPerformance?.appBundleBytes);
  if (Number.isFinite(bundleBytes) && bundleBytes > 0) return bundleBytes;
  return asNumber(frontendPerformance?.process?.heapUsedBytes);
}

function PerformanceMemoryChart({ points }: AnyRecord) {
  const rows = asArray(points);
  const values = rows.map((point: any) => asNumber(point.mb));
  const max = Math.max(1, ...values);
  const min = Math.max(0, Math.min(...values, 0));
  const range = Math.max(1, max - min);
  const chartValues = rows.length > 1 ? rows : [...rows, ...rows];
  const step = chartValues.length <= 1 ? 100 : 100 / (chartValues.length - 1);
  const linePoints = chartValues.map((point: any, index: number) => {
    const value = asNumber(point.mb);
    return `${(index * step).toFixed(2)},${(48 - ((value - min) / range) * 42).toFixed(2)}`;
  }).join(" ");
  const areaPoints = `0,50 ${linePoints} 100,50`;
  const latest = rows.at(-1);
  const first = rows[0];
  return h("article", { className: "performance-memory-card", "data-testid": "performance-memory-chart" },
    h("div", { className: "performance-memory-head" },
      h("strong", null, `Bwebui: ${latest ? `${asNumber(latest.mb).toFixed(1)}MB` : "--"}`),
      h("span", null, rows.length > 0 ? `${rows.length} samples` : "等待采样"),
    ),
    h("svg", { viewBox: "0 0 100 50", preserveAspectRatio: "none", role: "img", "aria-label": "Bwebui memory trend" },
      h("polygon", { points: areaPoints }),
      h("polyline", { points: linePoints }),
      h("line", { x1: "0", x2: "100", y1: "25", y2: "25" }),
    ),
    h("div", { className: "performance-axis-row" },
      h("span", null, first ? fmtClock(new Date(first.at)) : "--"),
      h("span", null, "时间"),
      h("span", null, latest ? fmtClock(new Date(latest.at)) : "--"),
    ),
    h("div", { className: "performance-axis-row" },
      h("span", null, `${min.toFixed(1)}`),
      h("span", null, "(MB)"),
      h("span", null, `${max.toFixed(1)}`),
    ),
  );
}

function PerformancePage({ onRaw }: AnyRecord) {
  const [snapshot, setSnapshot] = useState({ core: null, frontend: null });
  const [memorySamples, setMemorySamples] = useState([]);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const [codexPerf, setCodexPerf] = useState(null);
  const [codexPerfLoading, setCodexPerfLoading] = useState(false);

  async function load(): Promise<void> {
    setLoading(true);
    setError("");
    try {
      const [core, frontend] = await Promise.all([
        requestJson(`${cfg.apiBaseUrl}/performance`, { cache: "no-store" }),
        requestJson(`${cfg.apiBaseUrl}/frontend-performance`, { cache: "no-store" }),
      ]);
      setSnapshot({ core, frontend });
      const bytes = browserMemoryBytes(frontend);
      setMemorySamples((prev: any[]) => [...prev, { at: new Date().toISOString(), mb: bytes / (1024 * 1024) }].slice(-80));
    } catch (err) {
      setError(errorMessage(err, "性能指标加载失败"));
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void load();
    const timer = setInterval(() => void load(), 5000);
    return () => clearInterval(timer);
  }, []);

  async function runCodeQueueLoadTest(): Promise<void> {
    setCodexPerfLoading(true);
    setError("");
    setCodexPerf(null);
    try {
      const result = await requestJson(`${cfg.apiBaseUrl}/code-queue-load-test`, {
        method: "POST",
        body: JSON.stringify({
          targetMs: 1000,
          timeoutMs: 90000,
          url: cfg.frontendPublicUrl || window.location.origin,
        }),
      });
      setCodexPerf(result);
      void load();
    } catch (err) {
      setError(errorMessage(err, "Code Queue Playwright 测量失败"));
    } finally {
      setCodexPerfLoading(false);
    }
  }

  const components = summaryRows(snapshot);
  const failures = failureRows(snapshot);
  const operations = operationRows(snapshot);
  const slowRows = slowOperationRows(snapshot);
  const backendProcess = snapshot.core?.process || {};
  const frontendProcess = snapshot.frontend?.process || {};
  const codexStorage = snapshot.core?.database?.codeQueueStorage || {};
  const codexTotal = asNumber(codexStorage.total);
  const codexPerfResult = codexPerf?.result || {};
  const codexPerfWallMs = asNumber(codexPerfResult.wallMs, NaN);
  const codexPerfNetworkIdleMs = asNumber(codexPerfResult.networkIdleMs, NaN);
  const codexPerfWithinTarget = codexPerfResult.withinTarget === true;
  const codexPerfStatus = codexPerfLoading
    ? "running"
    : codexPerf === null
      ? "idle"
      : codexPerf.measurementOk === true
        ? codexPerfWithinTarget ? "passed" : "slow"
        : "failed";

  return h("div", { className: "performance-page", "data-testid": "performance-page" },
    h("div", { className: "performance-hero" },
      h("div", null,
        h("p", { className: "panel-eyebrow" }, "Unified Performance"),
        h(LoadingTitle, { title: "性能面板", loading: loading || codexPerfLoading }),
        h("p", null, "按组件统计 HTTP 请求、失败率、P95 延迟，并汇总 backend/frontend 内部操作耗时。"),
      ),
      h("div", { className: "inline-actions" },
        h("button", { type: "button", className: "ghost-btn", onClick: () => void runCodeQueueLoadTest(), disabled: codexPerfLoading, "data-testid": "code-queue-load-test-button" }, codexPerfLoading ? "测试中..." : "测试 Code Queue 加载"),
        h("button", { type: "button", className: "ghost-btn", onClick: () => void load(), disabled: loading, "data-testid": "performance-refresh-button" }, loading ? "刷新中" : "刷新"),
        h(RawButton, { title: "Performance Snapshot", data: snapshot, onOpen: onRaw, testId: "raw-performance" }),
      ),
    ),
    h(UniDeskErrorBanner, { error }),
    h("div", { className: "performance-top-grid" },
      h(PerformanceMemoryChart, { points: memorySamples }),
      h("div", { className: "performance-metric-stack" },
        h(MetricCard, { label: "backend RSS", value: fmtBytes(backendProcess.rssBytes), hint: `heap ${fmtBytes(backendProcess.heapUsedBytes)}` }),
        h(MetricCard, { label: "frontend RSS", value: fmtBytes(frontendProcess.rssBytes), hint: `bundle ${fmtBytes(snapshot.frontend?.appBundleBytes)}` }),
        h(MetricCard, { label: "Codex PG 任务", value: codexTotal || "--", hint: codexStorage.ok ? "unidesk_code_queue_tasks" : "等待表初始化", tone: codexStorage.ok ? "ok" : "warn" }),
        h(MetricCard, { label: "请求样本", value: asNumber(snapshot.core?.requests?.sampleCount) + asNumber(snapshot.frontend?.requests?.sampleCount), hint: "rolling window 3000" }),
      ),
    ),
    h(Panel, {
      title: "Code Queue 加载基准",
      eyebrow: "Playwright / target <1s",
      className: "codex-load-test-panel",
      loading: codexPerfLoading,
      actions: h("div", { className: "panel-actions" },
        h("button", { type: "button", className: "primary-btn", onClick: () => void runCodeQueueLoadTest(), disabled: codexPerfLoading, "data-testid": "code-queue-load-test-panel-button" }, codexPerfLoading ? "正在运行 Playwright..." : "手动触发测试"),
        codexPerf ? h(RawButton, { title: "Code Queue Load Test", data: codexPerf, onOpen: onRaw, testId: "raw-code-queue-load-test" }) : null,
      ),
    },
      h("div", { className: "codex-load-test-grid", "data-testid": "code-queue-load-test-result" },
        h(MetricCard, {
          label: "总耗时",
          value: codexPerfLoading ? "运行中" : Number.isFinite(codexPerfWallMs) ? fmtMs(codexPerfWallMs) : "--",
          hint: codexPerf === null ? "点击按钮启动远端 Playwright" : `目标 ${fmtMs(codexPerfResult.targetMs || 1000)} / ${codexPerfResult.url || "Code Queue"}`,
          tone: codexPerfStatus === "passed" ? "ok" : codexPerfStatus === "failed" || codexPerfStatus === "slow" ? "warn" : "",
        }),
        h(MetricCard, {
          label: "判定",
          value: codexPerfLoading ? "RUNNING" : codexPerfStatus === "passed" ? "PASS <1s" : codexPerfStatus === "slow" ? "SLOW" : codexPerfStatus === "failed" ? "FAILED" : "--",
          hint: codexPerf?.measurementOk === false ? String(codexPerf.error || codexPerfResult.error || "measurement failed").slice(0, 120) : "导航开始 -> DOMContentLoaded -> data-load-state=complete",
          tone: codexPerfStatus === "passed" ? "ok" : codexPerfStatus === "idle" || codexPerfStatus === "running" ? "" : "fail",
        }),
        h(MetricCard, {
          label: "Network idle",
          value: Number.isFinite(codexPerfNetworkIdleMs) ? fmtMs(codexPerfNetworkIdleMs) : "--",
          hint: `DOMContentLoaded ${fmtMs(codexPerfResult.domContentLoadedMs)} / ${codexPerfResult.networkIdleReached === false ? "未在 5s 内空闲" : "已空闲"}`,
          tone: Number.isFinite(codexPerfNetworkIdleMs) && codexPerfNetworkIdleMs <= 1000 ? "ok" : "warn",
        }),
        h(MetricCard, {
          label: "组件耗时",
          value: Number.isFinite(asNumber(codexPerfResult.componentLoadMs, NaN)) ? fmtMs(codexPerfResult.componentLoadMs) : "--",
          hint: `queue ${fmtMs(codexPerfResult.queueMs)} / detail ${fmtMs(codexPerfResult.detailMs)}`,
          tone: asNumber(codexPerfResult.componentLoadMs) > 1000 ? "warn" : "ok",
        }),
        h(MetricCard, {
          label: "Trace 规模",
          value: Number.isFinite(asNumber(codexPerfResult.transcriptRows, NaN)) ? String(codexPerfResult.transcriptRows) : "--",
          hint: `${codexPerfResult.visibleTaskCount ?? 0} visible tasks / ${codexPerfResult.partial ? "preview" : "complete"}`,
        }),
      ),
      codexPerfLoading ? h("div", { className: "performance-empty-line" }, "正在通过 main-server Host SSH 启动 Playwright，完成后会显示 wall time、组件耗时和最慢 API。") : null,
      codexPerf && Array.isArray(codexPerfResult.slowestApi) && codexPerfResult.slowestApi.length > 0 ? h("div", { className: "table-wrap performance-table-wrap compact codex-load-api-table" },
        h("table", { className: "performance-table" },
          h("thead", null, h("tr", null, ["API", "状态", "耗时"].map((label) => h("th", { key: label }, label)))),
          h("tbody", null, codexPerfResult.slowestApi.slice(0, 5).map((row: any, index: number) => h("tr", { key: `${row.url}-${index}` },
            h("td", null, h("code", null, row.url)),
            h("td", null, row.status),
            h("td", null, fmtMs(row.durationMs)),
          ))),
        ),
      ) : null,
    ),
    h("div", { className: "performance-grid" },
      h(Panel, { title: "组件汇总", eyebrow: "Requests", loading },
        components.length === 0 ? h(EmptyState, { title: "暂无请求样本", text: "刷新几次或打开页面后会自动形成组件统计" }) :
          h("div", { className: "table-wrap performance-table-wrap" }, h("table", { className: "performance-table" },
            h("thead", null, h("tr", null, ["组件", "请求数", "失败数", "失败率", "平均延迟", "P95"].map((label) => h("th", { key: label }, label)))),
            h("tbody", null, components.map((row: any) => h("tr", { key: row.component },
              h("td", null, h("code", null, row.component)),
              h("td", null, row.requestCount),
              h("td", null, row.failureCount),
              h("td", null, fmtPercent(asNumber(row.failureRate) * 100)),
              h("td", null, fmtMs(row.averageLatencyMs)),
              h("td", null, fmtMs(row.p95LatencyMs)),
            ))),
          )),
      ),
      h(Panel, { title: "最近失败请求", eyebrow: "Failures", loading },
        failures.length === 0 ? h("div", { className: "performance-empty-line" }, "最近没有失败请求") :
          h("div", { className: "table-wrap performance-table-wrap compact" }, h("table", { className: "performance-table" },
            h("thead", null, h("tr", null, ["时间", "来源", "组件", "状态", "路径"].map((label) => h("th", { key: label }, label)))),
            h("tbody", null, failures.map((row: any, index: number) => h("tr", { key: `${row.at}-${index}` },
              h("td", null, fmtDate(row.at)),
              h("td", null, row.source),
              h("td", null, h("code", null, row.component)),
              h("td", null, h(StatusBadge, { status: "failed" }, row.status)),
              h("td", null, h("code", null, row.path)),
            ))),
          )),
      ),
      h(Panel, { title: "内部操作汇总", eyebrow: "Operations", loading },
        operations.length === 0 ? h(EmptyState, { title: "暂无内部操作样本", text: "API 查询和代理请求会自动记录内部操作耗时" }) :
          h("div", { className: "table-wrap performance-table-wrap" }, h("table", { className: "performance-table" },
            h("thead", null, h("tr", null, ["服务", "操作", "次数", "平均延迟", "P95"].map((label) => h("th", { key: label }, label)))),
            h("tbody", null, operations.map((row: any) => h("tr", { key: `${row.service}-${row.operation}` },
              h("td", null, row.service),
              h("td", null, h("code", null, row.operation)),
              h("td", null, row.count),
              h("td", null, fmtMs(row.averageLatencyMs)),
              h("td", null, fmtMs(row.p95LatencyMs)),
            ))),
          )),
      ),
      h(Panel, { title: "最近慢操作", eyebrow: "Slowest", loading },
        slowRows.length === 0 ? h(EmptyState, { title: "暂无慢操作", text: "后端会记录最近窗口内耗时最高的内部操作" }) :
          h("div", { className: "table-wrap performance-table-wrap" }, h("table", { className: "performance-table" },
            h("thead", null, h("tr", null, ["时间", "操作", "耗时", "结果", "细节"].map((label) => h("th", { key: label }, label)))),
            h("tbody", null, slowRows.map((row: any, index: number) => h("tr", { key: `${row.at}-${row.operation}-${index}` },
              h("td", null, fmtDate(row.at)),
              h("td", null, h("code", null, row.operation)),
              h("td", null, fmtMs(row.durationMs)),
              h("td", null, row.ok ? "成功" : "失败"),
              h("td", null, row.detail || "-"),
            ))),
          )),
      ),
    ),
  );
}

function UpgradeControl({ provider, refresh, onRaw }: AnyRecord) {
  const [busyMode, setBusyMode] = useState("");
  const [result, setResult] = useState(null);
  const [error, setError] = useState("");

  async function run(mode: string): Promise<void> {
    setBusyMode(mode);
    setError("");
    try {
      const response = await requestJson(`${cfg.apiBaseUrl}/dispatch`, {
        method: "POST",
        body: JSON.stringify({
          providerId: provider.providerId,
          command: "provider.upgrade",
          payload: { mode, source: "frontend-resource-monitor", requestedAt: new Date().toISOString() },
        }),
      });
      setResult({ mode, ...response });
      await refresh();
    } catch (err) {
      setError(errorMessage(err, "升级命令下发失败"));
    } finally {
      setBusyMode("");
    }
  }

  return h(Panel, { title: "Provider Gateway 升级", eyebrow: "Remote Control", loading: Boolean(busyMode) },
    h("div", { className: "upgrade-control", "data-testid": "provider-upgrade-control" },
      h("p", null, "通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade；预检只生成升级计划，执行升级会调度节点本地 updater 容器。"),
      h("div", { className: "upgrade-target-line" },
        h("span", null, "指定 Provider"),
        h("code", null, provider.providerId),
        h(GatewayVersionBadge, { node: provider }),
      ),
      h("div", { className: "upgrade-actions" },
        h("button", { type: "button", className: "ghost-btn", disabled: Boolean(busyMode), onClick: () => run("plan"), "data-testid": "upgrade-plan-button" }, busyMode === "plan" ? "预检中" : "预检升级"),
        h("button", { type: "button", className: "ghost-btn danger", disabled: Boolean(busyMode), onClick: () => run("schedule"), "data-testid": "upgrade-schedule-button" }, busyMode === "schedule" ? "调度中" : "执行升级"),
      ),
      h(UniDeskErrorBanner, { error }),
      result ? h("div", { className: "upgrade-result" },
        h(StatusBadge, { status: result.status || "queued" }, result.status || "queued"),
        h("span", null, `${result.mode === "schedule" ? "执行升级" : "预检升级"} 已下发`),
        h("span", null, `指定版本 ${fmtGatewayVersion(nodeGatewayVersion(provider))}`),
        h("code", null, result.taskId || "--"),
        h(RawButton, { title: "Provider Upgrade Dispatch", data: result, onOpen: onRaw }),
      ) : h("span", { className: "muted" }, "升级任务结果会进入任务历史；执行升级可能导致 provider 短暂重连。"),
    ),
  );
}

function UpgradeRecordsTable({ records, onRaw, compact = false }: AnyRecord) {
  if (records.length === 0) {
    return h(EmptyState, { title: "暂无远程更新记录", text: "该节点还没有 provider.upgrade 任务；执行预检或升级后会在这里形成结构化记录" });
  }
  return h("div", { className: `upgrade-record-table-wrap table-wrap ${compact ? "compact" : ""}` }, h("table", { className: "upgrade-record-table" },
    h("thead", null, h("tr", null,
      h("th", null, "状态"),
      h("th", null, "模式"),
      h("th", null, "任务"),
      h("th", null, "来源"),
      h("th", null, "耗时"),
      h("th", null, "策略"),
      h("th", null, "Gateway 版本"),
      h("th", null, "结果记录"),
      h("th", null, "更新时间"),
      h("th", null, "操作"),
    )),
    h("tbody", null, records.map((task: any) => h("tr", { key: task.id, "data-testid": `gateway-upgrade-record-${safeId(task.id)}` },
      h("td", null, h(StatusBadge, { status: task.status })),
      h("td", null, h("span", { className: `mode-chip ${taskUpgradeMode(task)}` }, taskUpgradeMode(task) === "schedule" ? "执行升级" : "预检")),
      h("td", null, h("strong", null, "provider.upgrade"), h("code", null, task.id)),
      h("td", null, taskUpgradeSource(task)),
      h("td", null, h(TaskDurationCell, { task })),
      h("td", null, taskUpgradePolicy(task)),
      h("td", null, h("span", { className: "version-chip" }, taskUpgradeVersion(task))),
      h("td", null, h("span", { className: `upgrade-outcome ${String(task.status || "").toLowerCase()}` }, taskUpgradeOutcome(task))),
      h("td", null, fmtDate(task.updatedAt)),
      h("td", null, h(RawButton, { title: `Provider Upgrade Task ${task.id}`, data: taskRawButtonData(task), onOpen: onRaw })),
    ))),
  ));
}

function ProviderUpgradeRecordsPanel({ provider, tasks, onRaw, limit = 5 }: AnyRecord) {
  const records = providerUpgradeTasks(tasks, provider.providerId).slice(0, limit);
  return h(Panel, {
    title: "远程更新记录",
    eyebrow: provider.providerId,
    actions: h(GatewayVersionBadge, { node: provider }),
    className: "provider-upgrade-records-panel",
  },
    h("div", { "data-testid": `provider-upgrade-records-${safeId(provider.providerId)}` },
      h(UpgradeRecordsTable, { records, onRaw, compact: true }),
    ),
  );
}

function GatewayVersionPage({ nodes, tasks, onRaw }: AnyRecord) {
  const rows = useMemo(() => nodes.map((node: any) => {
    const records = providerUpgradeTasks(tasks, node.providerId);
    return { node, records, latest: latestScheduledUpgradeTask(records), capabilities: nodeCapabilities(node) };
  }), [nodes, tasks]);
  const totalRecords = rows.reduce((sum: number, row: any) => sum + row.records.length, 0);

  return h("div", { className: "gateway-page", "data-testid": "gateway-version-page" },
    h(Panel, { title: "Provider Gateway 版本", eyebrow: `${nodes.length} Providers / ${totalRecords} 更新记录` },
      nodes.length === 0 ? h(EmptyState, { title: "暂无 Provider 节点", text: "等待 provider-gateway 注册后显示版本号和升级记录" }) :
        h("div", { className: "table-wrap gateway-version-table-wrap" }, h("table", { className: "gateway-version-table" },
          h("thead", null, h("tr", null,
            h("th", null, "状态"),
            h("th", null, "Provider"),
            h("th", null, "Gateway 版本"),
            h("th", null, "升级策略"),
            h("th", null, "运维可用性"),
            h("th", null, "运行时间"),
            h("th", null, "能力"),
            h("th", null, "最近远程更新"),
            h("th", null, "操作"),
          )),
          h("tbody", null, rows.map((row: any) => h("tr", { key: row.node.providerId },
            h("td", null, h(StatusBadge, { status: row.node.status })),
            h("td", null, h("strong", null, row.node.name), h("code", null, row.node.providerId)),
            h("td", null, h(GatewayVersionBadge, { node: row.node })),
            h("td", null, nodeGatewayPolicy(row.node)),
            h("td", null, h(NodeAvailabilityStrip, { node: row.node })),
            h("td", null, nodeGatewayStartedAt(row.node) ? fmtDate(nodeGatewayStartedAt(row.node)) : "待新版上报"),
            h("td", null, h("div", { className: "capability-row" },
              row.capabilities.length === 0 ? h("span", { className: "muted" }, "未声明") :
                row.capabilities.slice(0, 5).map((item: string) => h("span", { key: item, className: "data-chip" }, item)),
            )),
            h("td", null, row.latest ? h("div", { className: "latest-upgrade-cell" },
              h(StatusBadge, { status: row.latest.status }),
              h("span", null, `${taskUpgradeMode(row.latest) === "schedule" ? "执行升级" : "预检"} / ${fmtDate(row.latest.updatedAt)}`),
              h("small", null, `Gateway ${taskUpgradeVersion(row.latest)}`),
              h("small", null, taskUpgradeOutcome(row.latest)),
            ) : h("span", { className: "muted" }, "暂无记录")),
            h("td", null, h(RawButton, { title: `Provider ${row.node.providerId}`, data: row.node, onOpen: onRaw })),
          ))),
        )),
    ),
    h(Panel, { title: "远程更新记录", eyebrow: "Structured provider.upgrade records" },
      nodes.length === 0 ? h(EmptyState, { title: "暂无记录", text: "没有 provider 节点时不会生成远程更新记录" }) :
        h("div", { className: "gateway-record-grid" }, rows.map((row: any) => h("article", {
          key: row.node.providerId,
          className: "gateway-record-card",
          "data-testid": `gateway-records-${safeId(row.node.providerId)}`,
        },
          h("div", { className: "gateway-record-head" },
            h("div", null, h("strong", null, row.node.name), h("code", null, row.node.providerId)),
            h(GatewayVersionBadge, { node: row.node }),
          ),
          h("div", { className: "gateway-record-meta" },
            h("span", null, `心跳 ${fmtDate(row.node.lastHeartbeat)}`),
            h("span", null, `策略 ${nodeGatewayPolicy(row.node)}`),
            h("span", null, `${row.records.length} 条记录`),
          ),
          h(UpgradeRecordsTable, { records: row.records.slice(0, 8), onRaw, compact: true }),
        ))),
    ),
  );
}

function dockerStateTone(state: string): string {
  if (state === "running") return "online";
  if (state === "paused" || state === "restarting") return "warn";
  if (state === "exited" || state === "dead") return "offline";
  return "internal";
}

function isHashVolumeName(name: string): boolean {
  return /^[a-f0-9]{48,64}$/i.test(name);
}

function isDatabaseVolume(volume: AnyRecord): boolean {
  const name = String(volume?.name || "");
  const labels = String(volume?.labels || "");
  return name === "unidesk_pgdata_10gb" || labels.includes("com.docker.compose.volume=unidesk_pgdata_10gb") || name.toLowerCase().includes("pgdata");
}

function volumeRank(volume: AnyRecord): number {
  const name = String(volume?.name || "");
  const labels = String(volume?.labels || "");
  if (isDatabaseVolume(volume)) return 0;
  if (labels.includes("com.docker.compose.project=unidesk")) return 1;
  if (!isHashVolumeName(name)) return 2;
  return 3;
}

function sortVolumes(volumes: AnyRecord[]): AnyRecord[] {
  return [...volumes].sort((left, right) => {
    const rankDelta = volumeRank(left) - volumeRank(right);
    if (rankDelta !== 0) return rankDelta;
    return String(left.name || "").localeCompare(String(right.name || ""));
  });
}

function DockerStatusPage({ nodes, dockerStatuses, onRaw }: AnyRecord) {
  const [selectedProvider, setSelectedProvider] = useState("");
  const merged = useMemo(() => nodes.map((node: any) => {
    const status = dockerStatuses.find((item: any) => item.providerId === node.providerId);
    return { ...node, dockerStatus: status?.dockerStatus || null, dockerUpdatedAt: status?.updatedAt || null };
  }), [nodes, dockerStatuses]);
  const active = merged.find((node: any) => node.providerId === selectedProvider) || merged[0] || null;
  useEffect(() => {
    if (!selectedProvider && merged[0]) setSelectedProvider(merged[0].providerId);
  }, [merged.length, selectedProvider]);

  if (!active) {
    return h(EmptyState, { title: "暂无 Docker 节点", text: "等待 provider 上报 Docker daemon 状态" });
  }

  const status = active.dockerStatus;
  const isMainServer = active.providerId === "main-server";
  const counts = status?.counts || {};
  const daemon = status?.daemon || {};
  const containers = status?.containers || [];
  const images = status?.images || [];
  const volumes = sortVolumes(status?.volumes || []);
  const databaseVolume = isMainServer ? volumes.find(isDatabaseVolume) : null;
  const networks = status?.networks || [];
  const runningContainers = containers.filter((item: any) => item.state === "running");
  const stoppedContainers = containers.filter((item: any) => item.state !== "running");

  return h("div", { className: "docker-page", "data-testid": "docker-status-page" },
    h("div", { className: "docker-node-strip" },
      merged.map((node: any) => h("button", {
        key: node.providerId,
        type: "button",
        className: `docker-node-tile ${active.providerId === node.providerId ? "active" : ""}`,
        onClick: () => setSelectedProvider(node.providerId),
      },
        h("span", { className: `pulse ${node.status}` }),
        h("strong", null, node.name),
        h("code", null, node.providerId),
        h("span", null, node.dockerStatus ? `Docker ${node.dockerStatus.ok ? "ready" : "degraded"}` : "等待上报"),
      )),
    ),
    h("div", { className: "docker-layout" },
      h(Panel, {
        title: "Docker Desktop 视图",
        eyebrow: active.name,
        className: "docker-main-panel",
        actions: status ? h(RawButton, { title: `Docker ${active.providerId}`, data: status, onOpen: onRaw }) : null,
      },
        !status ? h(EmptyState, { title: "Docker 状态未上报", text: "provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network" }) :
          h("div", null,
            h("div", { className: "docker-hero" },
              h("div", null,
                h("p", { className: "panel-eyebrow" }, "Daemon"),
                h("h3", null, daemon.name || active.providerId),
                h("div", { className: "docker-meta" },
                  h("span", null, daemon.serverVersion ? `Engine ${daemon.serverVersion}` : "Engine --"),
                  h("span", null, daemon.operatingSystem || "OS --"),
                  h("span", null, daemon.architecture || "arch --"),
                  h("span", null, `${daemon.cpus || 0} CPU / ${fmtBytes(daemon.memoryBytes)}`),
                ),
              ),
              h(StatusBadge, { status: status.ok ? "online" : "warn" }, status.ok ? "Docker Ready" : "Docker Degraded"),
            ),
            h("div", { className: "docker-metrics" },
              h(MetricCard, { label: "Containers", value: counts.containers ?? containers.length, hint: `${counts.running ?? runningContainers.length} running / ${counts.stopped ?? stoppedContainers.length} stopped`, tone: "ok" }),
              h(MetricCard, { label: "Images", value: counts.images ?? images.length, hint: `${counts.daemonImages ?? counts.images ?? images.length} daemon images` }),
              h(MetricCard, { label: "Volumes", value: counts.volumes ?? volumes.length, hint: isMainServer ? (databaseVolume ? "database volume visible" : "database volume missing") : "node local volumes", tone: databaseVolume ? "ok" : "" }),
              h(MetricCard, { label: "Networks", value: counts.networks ?? networks.length, hint: daemon.driver ? `driver ${daemon.driver}` : "docker networks" }),
            ),
            isMainServer ? h(DatabaseVolumeCard, { volume: databaseVolume, volumeCount: volumes.length }) : null,
            h("div", { className: "docker-section-head" },
              h("h3", null, "Containers"),
              h("span", null, `updated ${fmtDate(active.dockerUpdatedAt || status.collectedAt)}`),
            ),
            h("div", { className: "docker-container-table table-wrap", "data-testid": "docker-container-table" }, h("table", null,
              h("thead", null, h("tr", null, h("th", null, "状态"), h("th", null, "容器"), h("th", null, "镜像"), h("th", null, "端口"), h("th", null, "运行时间"), h("th", null, "重启策略"), h("th", null, "PID"), h("th", null, "大小"))),
              h("tbody", null, containers.length === 0 ? h("tr", null, h("td", { colSpan: 8 }, "暂无容器")) : containers.map((item: any) => h("tr", { key: `${item.id}-${item.name}` },
                h("td", null, h(StatusBadge, { status: dockerStateTone(item.state) }, item.state || "unknown")),
                h("td", null, h("strong", null, item.name || "--"), h("code", null, item.id || "--")),
                h("td", null, item.image || "--"),
                h("td", null, item.ports || h("span", { className: "muted" }, "未发布")),
                h("td", null, item.runningFor || item.status || "--"),
                h("td", null, item.restartPolicy ? h(StatusBadge, { status: item.restartPolicy === "always" ? "online" : "warn" }, item.restartPolicy) : "--"),
                h("td", null, item.pidMode ? h("code", null, item.pidMode) : "--"),
                h("td", null, item.size || "--"),
              ))),
            )),
          ),
      ),
      h("div", { className: "docker-side-stack" },
        h(DockerSidePanel, { title: "Images", items: images, render: (image: any) => h("article", { key: `${image.id}-${image.repository}`, className: "docker-side-row" }, h("strong", null, `${image.repository}:${image.tag}`), h("span", null, image.size || "--"), h("code", null, image.id || "--")) }),
        h(DockerSidePanel, { title: "Volumes", items: volumes, limit: volumes.length, render: (volume: any) => h("article", { key: volume.name, className: `docker-side-row volume-row ${isMainServer && isDatabaseVolume(volume) ? "database-volume" : ""}`, "data-testid": isMainServer && isDatabaseVolume(volume) ? "database-volume-row" : undefined },
          h("strong", null, volume.name),
          h("span", null, isMainServer && isDatabaseVolume(volume) ? "PostgreSQL" : isHashVolumeName(String(volume.name || "")) ? "anonymous" : "named"),
          h("code", null, volume.mountpoint || volume.driver || volume.scope || "--"),
        ) }),
        h(DockerSidePanel, { title: "Networks", items: networks, render: (network: any) => h("article", { key: network.id || network.name, className: "docker-side-row" }, h("strong", null, network.name), h("span", null, network.driver || "--"), h("code", null, network.id || "--")) }),
      ),
    ),
  );
}

function DatabaseVolumeCard({ volume, volumeCount }: AnyRecord) {
  return h("section", { className: `docker-volume-focus ${volume ? "ready" : "missing"}`, "data-testid": "database-volume-card" },
    h("div", { className: "volume-focus-head" },
      h("span", { className: "panel-eyebrow" }, "Database Named Volume"),
      h(StatusBadge, { status: volume ? "online" : "warn" }, volume ? "FOUND" : "MISSING"),
    ),
    volume ? h("div", { className: "volume-focus-body" },
      h("strong", null, volume.name),
      h("span", null, "PostgreSQL data volume for unidesk-database"),
      h("div", { className: "volume-route" },
        h("code", null, volume.mountpoint || "/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),
        h("span", null, "->"),
        h("code", null, "unidesk-database:/var/lib/postgresql/data"),
      ),
      h("div", { className: "docker-meta compact" },
        h("span", null, `driver ${volume.driver || "--"}`),
        h("span", null, `scope ${volume.scope || "--"}`),
        h("span", null, `${volumeCount} volumes reported`),
      ),
    ) : h("div", { className: "volume-focus-body" },
      h("strong", null, "unidesk_pgdata_10gb"),
      h("span", null, "当前 Docker 快照没有发现数据库命名卷；请检查 provider-gateway 的 Docker volume 上报。"),
    ),
  );
}

function DockerSidePanel({ title, items, render, limit }: AnyRecord) {
  const visibleItems = items.slice(0, limit ?? 12);
  const hiddenCount = Math.max(0, items.length - visibleItems.length);
  return h(Panel, { title, eyebrow: `${items.length} items`, className: "docker-side-panel" },
    items.length === 0 ? h(EmptyState, { title: `暂无 ${title}`, text: "等待 Docker 状态采集" }) :
      h("div", { className: "docker-side-list" },
        visibleItems.map(render),
        hiddenCount > 0 ? h("div", { className: "docker-side-more" }, `+ ${hiddenCount} more`) : null,
      ),
  );
}

function MicroserviceCatalogPage({ microservices, onRaw, onNavigate }: AnyRecord) {
  const privateServices = microservices.filter((service: any) => microserviceBackend(service).public === false);
  return h("div", { className: "microservice-page", "data-testid": "microservice-catalog-page" },
    h(Panel, { title: "用户服务目录", eyebrow: "Provider Mounted User Services" },
      h("div", { className: "metric-grid" },
        h(MetricCard, { label: "服务总数", value: microservices.length, hint: "config.json 用户服务登记" }),
        h(MetricCard, { label: "私有后端", value: privateServices.length, hint: "不直接暴露公网", tone: "ok" }),
        h(MetricCard, { label: "D601 服务", value: microservices.filter((service: any) => service.providerId === "D601").length, hint: "compute-node docker" }),
        h(MetricCard, { label: "集成前端", value: microservices.filter((service: any) => service.frontend?.integrated).length, hint: "UniDesk React 页面" }),
      ),
    ),
    h(Panel, { title: "外部静态入口", eyebrow: "External Link" },
      h("div", { className: "endpoint-list hwlab-entry-list" },
        h("article", { className: "hwlab-entry-card", "data-testid": "hwlab-entry-card" },
          h("b", null, "HWLAB"),
          h("span", null, HWLAB_URL),
          h("span", null, "external static link"),
          h("div", { className: "microservice-actions hwlab-entry-actions" },
            h("button", {
              type: "button",
              className: "ghost-btn",
              "data-testid": "hwlab-open-current-from-catalog",
              onClick: () => window.location.assign(HWLAB_URL),
            }, "当前窗口"),
            h("a", {
              className: "ghost-btn",
              href: HWLAB_URL,
              target: "_blank",
              rel: "noreferrer",
              "data-testid": "hwlab-open-new-from-catalog",
            }, "新窗口"),
          ),
        ),
      ),
      h("p", { className: "muted paragraph" }, "该入口仅用于外部静态跳转，不会进入 microservice health、proxy 或运行态探测。"),
    ),
    h(Panel, { title: "服务映射", eyebrow: "Repo Reference + Runtime" },
      microservices.length === 0 ? h(EmptyState, { title: "暂无用户服务", text: "在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射" }) :
        h("div", { className: "table-wrap" }, h("table", { className: "microservice-table" },
          h("thead", null, h("tr", null, h("th", null, "服务"), h("th", null, "Provider"), h("th", null, "代码引用"), h("th", null, "Docker 引用"), h("th", null, "后端映射"), h("th", null, "开发入口"), h("th", null, "运行态"), h("th", null, "操作"))),
          h("tbody", null, microservices.map((service: any) => {
            const runtime = microserviceRuntime(service);
            const repository = microserviceRepository(service);
            const backend = microserviceBackend(service);
            const availability = runtime.availability || {};
            const availabilityStatus = availability.status || (runtime.providerStatus === "online" ? "unknown" : "unhealthy");
            return h("tr", { key: service.id, "data-testid": `microservice-row-${safeId(service.id)}` },
              h("td", null, h("strong", null, service.name), h("code", null, service.id)),
              h("td", null, h("strong", null, runtime.providerName || service.providerId), h("code", null, service.providerId)),
              h("td", null, h("span", null, repository.url || "--"), h("code", null, repository.commitId || "--")),
              h("td", null, h("span", null, repository.composeFile || "--"), h("code", null, `${repository.composeService || "--"} / ${repository.containerName || "--"}`)),
              h("td", null,
                h(StatusBadge, { status: backend.public ? "warn" : "online" }, backend.public ? "public" : "private"),
                h("code", null, `${backend.nodeBindHost || "--"}:${backend.nodePort || "--"} -> ${backend.proxyMode || "--"}`),
              ),
              h("td", null, h("span", null, service.development?.sshPassthrough ? "SSH 透传" : "未配置"), h("code", null, service.development?.worktreePath || "--")),
              h("td", null,
                h(StatusBadge, { status: availabilityStatus === "healthy" ? "online" : availabilityStatus === "unknown" ? "warn" : "failed" }, availabilityStatus),
                h("span", null, availability.reason || runtime.providerStatus || "unknown"),
                h(DataSummary, { data: runtime.container, empty: "容器快照未上报" }),
              ),
              h("td", null,
                h("div", { className: "microservice-actions" },
                  service.id === "findjob" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "findjob"), "data-testid": "open-findjob-button" }, "打开") : null,
                  service.id === "pipeline" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "pipeline"), "data-testid": "open-pipeline-button" }, "打开") : null,
                  service.id === "todo-note" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "todo-note"), "data-testid": "open-todo-note-button" }, "打开") : null,
                  service.id === "met-nonlinear" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "met-nonlinear"), "data-testid": "open-met-nonlinear-button" }, "打开") : null,
                  service.id === "claudeqq" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "claudeqq"), "data-testid": "open-claudeqq-button" }, "打开") : null,
                  service.id === "baidu-netdisk" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "baidu-netdisk"), "data-testid": "open-baidu-netdisk-button" }, "打开") : null,
                  service.id === "oa-event-flow" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "oa-event-flow"), "data-testid": "open-oa-event-flow-button" }, "打开") : null,
                  service.id === "k3sctl-adapter" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "k3sctl"), "data-testid": "open-k3sctl-button" }, "打开") : null,
                  service.id === "code-queue" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "code-queue"), "data-testid": "open-code-queue-button" }, "打开") : null,
                  service.id === "mdtodo" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "mdtodo"), "data-testid": "open-mdtodo-button" }, "打开") : null,
                  service.id === "decision-center" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "decision-center"), "data-testid": "open-decision-center-button" }, "打开") : null,
                  service.id === "project-manager" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "project-manager"), "data-testid": "open-project-manager-button" }, "打开") : null,
                  h(RawButton, { title: `用户服务 ${service.id}`, data: service, onOpen: onRaw }),
                ),
              ),
            );
          })),
        )),
    ),
  );
}

function DispatchPage({ nodes, onDispatched, onRaw }: AnyRecord) {
  const onlineNodes = nodes.filter((node: any) => node.status === "online");
  const [providerId, setProviderId] = useState(onlineNodes[0]?.providerId || nodes[0]?.providerId || "");
  const [command, setCommand] = useState("docker.ps");
  const [source, setSource] = useState("frontend");
  const [note, setNote] = useState("operator-check");
  const [priority, setPriority] = useState("normal");
  const [rawOpen, setRawOpen] = useState(false);
  const [rawPayload, setRawPayload] = useState("");
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState(null);
  const [error, setError] = useState("");

  useEffect(() => {
    if (!providerId && (onlineNodes[0]?.providerId || nodes[0]?.providerId)) setProviderId(onlineNodes[0]?.providerId || nodes[0].providerId);
  }, [nodes.length, onlineNodes.length, providerId]);

  function structuredPayload(): AnyRecord {
    return { source, note, priority };
  }

  function revealRawPayload(): void {
    setRawPayload(JSON.stringify(structuredPayload(), null, 2));
    setRawOpen(true);
  }

  async function submit(event: any) {
    event.preventDefault();
    setBusy(true);
    setError("");
    try {
      const payload = rawOpen ? JSON.parse(rawPayload || "{}") : structuredPayload();
      const response = await requestJson(`${cfg.apiBaseUrl}/dispatch`, {
        method: "POST",
        body: JSON.stringify({ providerId, command, payload }),
      });
      setResult(response);
      await onDispatched();
    } catch (err) {
      setError(errorMessage(err, "下发失败"));
    } finally {
      setBusy(false);
    }
  }

  return h("div", { className: "page-grid dispatch-grid" },
    h(Panel, { title: "下发任务", eyebrow: "Real WebSocket Dispatch" },
      h("form", { className: "dispatch-form", onSubmit: submit },
        h("label", null, "Provider", h("select", { value: providerId, onChange: (event: any) => setProviderId(event.target.value) },
          nodes.map((node: any) => h("option", { key: node.providerId, value: node.providerId }, `${node.name} / ${node.providerId}`)),
        )),
        h("label", null, "Command", h("select", { value: command, onChange: (event: any) => setCommand(event.target.value) },
          h("option", { value: "docker.ps" }, "docker.ps"),
          h("option", { value: "host.ssh" }, "host.ssh"),
          h("option", { value: "microservice.http" }, "microservice.http"),
          h("option", { value: "echo" }, "echo"),
        )),
        h("label", null, "来源", h("input", { value: source, onChange: (event: any) => setSource(event.target.value) })),
        h("label", null, "备注", h("input", { value: note, onChange: (event: any) => setNote(event.target.value) })),
        h("label", null, "优先级", h("select", { value: priority, onChange: (event: any) => setPriority(event.target.value) },
          h("option", { value: "normal" }, "normal"),
          h("option", { value: "low" }, "low"),
          h("option", { value: "urgent" }, "urgent"),
        )),
        h("div", { className: "dispatch-actions" },
          h("button", { type: "button", className: "ghost-btn", onClick: revealRawPayload }, "查看原始JSON"),
          h("button", { type: "submit", disabled: busy || !providerId }, busy ? "下发中" : "下发任务"),
        ),
        rawOpen ? h("label", { className: "raw-editor-label" }, "高级 Payload", h("textarea", { className: "raw-editor", value: rawPayload, onChange: (event: any) => setRawPayload(event.target.value) })) : null,
        h(UniDeskErrorBanner, { error, wide: true }),
      ),
    ),
    h(Panel, { title: "下发结果", eyebrow: "Response" },
      result ? h("div", { className: "result-card" },
        h(StatusBadge, { status: result.status || "queued" }, result.status || "queued"),
        h("dl", null,
          h("dt", null, "Task ID"), h("dd", null, h("code", null, result.taskId || "--")),
          h("dt", null, "Provider 在线"), h("dd", null, summarizeValue(result.providerOnline)),
        ),
        h(RawButton, { title: "Dispatch Response", data: result, onOpen: onRaw }),
      ) : h(EmptyState, { title: "等待操作", text: "任务响应会以结构化结果卡展示" }),
    ),
  );
}

function TaskCompactRow({ task, onRaw }: AnyRecord) {
  return h("article", { className: "compact-row" },
    h(StatusBadge, { status: task.status }),
    h("div", null, h("strong", null, task.command), h("code", null, task.id)),
    h("span", null, isPendingTask(task) ? `已等待 ${fmtRelativeAge(task.updatedAt)}` : `耗时 ${fmtDuration(taskElapsedSeconds(task) ?? 0)}`),
    h(RawButton, { title: `Task ${task.id}`, data: taskRawButtonData(task), onOpen: onRaw }),
  );
}

function TaskDurationCell({ task }: AnyRecord) {
  const elapsed = taskElapsedSeconds(task);
  const pending = isPendingTask(task);
  return h("div", { className: "task-duration" },
    h("strong", null, elapsed === null ? "--" : fmtDuration(elapsed)),
    h("span", null, pending ? `已运行 / 创建 ${fmtDate(task.createdAt)}` : `创建 ${fmtDate(task.createdAt)}`),
  );
}

function TaskDiagnosticCell({ task }: AnyRecord) {
  const status = String(task?.status || "").toLowerCase();
  const result = task?.result;
  const resultRecord = result && typeof result === "object" && !Array.isArray(result) ? result as AnyRecord : {};
  const metaKeys = ["exitCode", "code", "signal", "timeoutMs", "previousStatus", "mode"];
  const metas = metaKeys.filter((key) => resultRecord[key] !== undefined && resultRecord[key] !== null);
  if (status === "failed") {
    const reason = taskFailureReason(task);
    return h("div", { className: "task-diagnostic failed" },
      h("b", null, "失败原因"),
      h("span", { className: "diagnostic-reason" }, summarizeValue(reason)),
      metas.length > 0 ? h("div", { className: "diagnostic-meta" }, metas.map((key) =>
        h("span", { key, className: "data-chip" }, h("b", null, key), h("span", null, summarizeValue(resultRecord[key]))),
      )) : null,
    );
  }
  if (isPendingTask(task)) {
    return h("div", { className: "task-diagnostic warn" },
      h("b", null, "等待终态"),
      h("span", null, `最后更新 ${fmtRelativeAge(task.updatedAt)} 前`),
    );
  }
  return h("div", { className: "task-diagnostic ok" },
    h("b", null, "完成摘要"),
    h(DataSummary, { data: result, empty: "无执行输出" }),
  );
}

function TaskPendingPage({ tasks, onRaw }: AnyRecord) {
  const pending = tasks.filter(isPendingTask);
  return h("div", { "data-testid": "pending-task-page" },
    h(Panel, { title: "待处理任务", eyebrow: `${pending.length} Pending` },
      pending.length === 0 ? h(EmptyState, { title: "当前无待处理任务", text: "queued / dispatched / running 会在超时后自动转为 failed；历史记录仍可在任务历史中查看" }) :
        h("div", { className: "table-wrap", "data-testid": "pending-task-table" }, h("table", null,
          h("thead", null, h("tr", null, h("th", null, "状态"), h("th", null, "任务"), h("th", null, "Provider"), h("th", null, "已等待"), h("th", null, "载荷摘要"), h("th", null, "操作"))),
          h("tbody", null, pending.map((task: any) => h("tr", { key: task.id },
            h("td", null, h(StatusBadge, { status: task.status })),
            h("td", null, h("strong", null, task.command), h("code", null, task.id)),
            h("td", null, h("code", null, task.providerId)),
            h("td", null, fmtRelativeAge(task.updatedAt)),
            h("td", null, h(DataSummary, { data: task.payload })),
            h("td", null, h(RawButton, { title: `Pending Task ${task.id}`, data: taskRawButtonData(task), onOpen: onRaw })),
          ))),
        )),
    ),
  );
}

function TaskHistoryPage({ tasks, onRaw }: AnyRecord) {
  return h("div", { "data-testid": "task-history-page" },
    h(Panel, { title: "任务历史", eyebrow: `${tasks.length} Tasks` },
    tasks.length === 0 ? h(EmptyState, { title: "暂无任务", text: "下发任务后会在这里看到生命周期" }) :
      h("div", { className: "table-wrap" }, h("table", { className: "task-history-table" },
        h("thead", null, h("tr", null, h("th", null, "状态"), h("th", null, "任务"), h("th", null, "Provider"), h("th", null, "任务耗时"), h("th", null, "载荷摘要"), h("th", null, "诊断信息"), h("th", null, "更新时间"), h("th", null, "操作"))),
        h("tbody", null, tasks.map((task: any) => h("tr", { key: task.id, "data-testid": `task-row-${safeId(task.id)}` },
          h("td", null, h(StatusBadge, { status: task.status })),
          h("td", null, h("strong", null, task.command), h("code", null, task.id)),
          h("td", null, h("code", null, task.providerId)),
          h("td", null, h(TaskDurationCell, { task })),
          h("td", null, h(DataSummary, { data: task.payload })),
          h("td", null, h(TaskDiagnosticCell, { task })),
          h("td", null, fmtDate(task.updatedAt)),
          h("td", null, h(RawButton, { title: `Task ${task.id}`, data: taskRawButtonData(task), onOpen: onRaw })),
        ))),
      )),
    ),
  );
}

function TaskResultsPage({ tasks, onRaw }: AnyRecord) {
  const finished = tasks.filter((task: any) => ["succeeded", "failed"].includes(task.status));
  return h(Panel, { title: "执行结果", eyebrow: "Finished Tasks" },
    finished.length === 0 ? h(EmptyState, { title: "暂无结果", text: "任务完成后展示 provider 返回的结构化摘要" }) :
      h("div", { className: "result-grid" }, finished.map((task: any) => h("article", { key: task.id, className: "result-card" },
        h("div", { className: "node-card-head" }, h("strong", null, task.command), h(StatusBadge, { status: task.status })),
        h("code", null, task.id),
        h(DataSummary, { data: task.result, empty: "无执行输出" }),
        h(RawButton, { title: `Task Result ${task.id}`, data: taskRawButtonData(task), onOpen: onRaw }),
      ))),
  );
}

function scheduleSpecLabel(schedule: any): string {
  if (!schedule || typeof schedule !== "object") return "--";
  if (schedule.type === "interval") return `每 ${fmtDuration(Number(schedule.everySeconds || 0))}`;
  return `每天 ${schedule.timeOfDay || "03:00"} UTC`;
}

function scheduleActionLabel(action: any): string {
  if (!action || typeof action !== "object") return "--";
  if (action.type === "pgdata_backup") return `PGDATA -> ${action.remoteBaseDir || "/SERVER_DATA/UNIDESK_PG_DATA"}`;
  if (action.type === "dispatch") return `${action.providerId || "--"} / ${action.command || "--"}`;
  return String(action.type || "--");
}

function scheduleRunTone(status: any): string {
  const value = String(status || "").toLowerCase();
  if (value === "succeeded") return "online";
  if (value === "failed") return "failed";
  if (value === "running" || value === "queued") return "warn";
  return value;
}

function scheduleRunDuration(run: any): string {
  const ms = Number(run?.durationMs);
  if (Number.isFinite(ms) && ms >= 0) return fmtDuration(ms / 1000);
  const started = timeMs(run?.startedAt || run?.createdAt);
  if (started === null) return "--";
  const finished = timeMs(run?.finishedAt);
  const ended = finished ?? Date.now();
  return fmtDuration(Math.max(0, (ended - started) / 1000));
}

function defaultScheduleForm(nodes: any[]): AnyRecord {
  return {
    id: "unidesk-pgdata-baidu-daily",
    name: "PGDATA daily Baidu Netdisk backup",
    description: "Daily PostgreSQL physical base backup uploaded to Baidu Netdisk /SERVER_DATA with monthly rotation.",
    enabled: true,
    timeOfDay: "03:30",
    actionType: "pgdata_backup",
    providerId: nodes[0]?.providerId || "main-server",
    command: "echo",
    payloadJson: JSON.stringify({ source: "scheduled-task", message: "hello from scheduler" }, null, 2),
    remoteBaseDir: "/SERVER_DATA/UNIDESK_PG_DATA",
    stagingSubdir: "server-data/unidesk-pg-data",
    timeoutMs: "3600000",
  };
}

function TaskScheduledPage({ schedules, scheduleRuns, nodes, refresh, onRaw }: AnyRecord) {
  const [form, setForm] = useState(defaultScheduleForm(nodes || []));
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [notice, setNotice] = useState("");
  const sortedRuns = [...(scheduleRuns || [])].sort((left: any, right: any) => (timeMs(right.updatedAt) ?? 0) - (timeMs(left.updatedAt) ?? 0));

  function update(key: string, value: any): void {
    setForm((previous: AnyRecord) => ({ ...previous, [key]: value }));
  }

  function editSchedule(schedule: any): void {
    const action = schedule?.action || {};
    setForm({
      id: schedule?.id || "",
      name: schedule?.name || "",
      description: schedule?.description || "",
      enabled: schedule?.enabled !== false,
      timeOfDay: schedule?.schedule?.timeOfDay || "03:30",
      actionType: action.type || "dispatch",
      providerId: action.providerId || nodes[0]?.providerId || "main-server",
      command: action.command || "echo",
      payloadJson: JSON.stringify(action.payload || { source: "scheduled-task" }, null, 2),
      remoteBaseDir: action.remoteBaseDir || "/SERVER_DATA/UNIDESK_PG_DATA",
      stagingSubdir: action.stagingSubdir || "server-data/unidesk-pg-data",
      timeoutMs: String(action.timeoutMs || 3600000),
    });
    setNotice(`正在编辑 ${schedule?.id || ""}`);
  }

  function scheduleBody(): AnyRecord {
    const base = {
      id: form.id,
      name: form.name,
      description: form.description,
      enabled: form.enabled,
      concurrencyPolicy: "skip",
      schedule: { type: "daily", timeOfDay: form.timeOfDay, timezone: "Etc/UTC" },
    };
    if (form.actionType === "pgdata_backup") {
      return {
        ...base,
        action: {
          type: "pgdata_backup",
          volumeName: "unidesk_pgdata_10gb",
          remoteBaseDir: form.remoteBaseDir,
          stagingSubdir: form.stagingSubdir,
          timeoutMs: Number(form.timeoutMs) || 3600000,
          cleanupLocal: true,
        },
      };
    }
    return {
      ...base,
      action: {
        type: "dispatch",
        providerId: form.providerId,
        command: form.command,
        payload: JSON.parse(form.payloadJson || "{}"),
        timeoutMs: Number(form.timeoutMs) || 600000,
      },
    };
  }

  async function save(event: any): Promise<void> {
    event.preventDefault();
    setBusy(true);
    setError("");
    setNotice("");
    try {
      const body = scheduleBody();
      const id = encodeURIComponent(String(body.id));
      await requestJson(`${cfg.apiBaseUrl}/schedules/${id}`, { method: "PUT", body: JSON.stringify(body) });
      setNotice("定时任务已保存");
      await refresh();
    } catch (err) {
      setError(errorMessage(err, "保存定时任务失败"));
    } finally {
      setBusy(false);
    }
  }

  async function deleteSchedule(schedule: any): Promise<void> {
    if (!schedule?.id) return;
    setBusy(true);
    setError("");
    setNotice("");
    try {
      await requestJson(`${cfg.apiBaseUrl}/schedules/${encodeURIComponent(schedule.id)}`, { method: "DELETE" });
      setNotice(`已删除 ${schedule.id}`);
      await refresh();
    } catch (err) {
      setError(errorMessage(err, "删除定时任务失败"));
    } finally {
      setBusy(false);
    }
  }

  async function runNow(schedule: any): Promise<void> {
    if (!schedule?.id) return;
    setBusy(true);
    setError("");
    setNotice("");
    try {
      const response = await requestJson(`${cfg.apiBaseUrl}/schedules/${encodeURIComponent(schedule.id)}/run`, { method: "POST", body: "{}" });
      setNotice(`已触发 ${schedule.id} / ${response?.run?.id || "run"}`);
      await refresh();
    } catch (err) {
      setError(errorMessage(err, "触发定时任务失败"));
    } finally {
      setBusy(false);
    }
  }

  return h("div", { className: "page-grid scheduled-task-page", "data-testid": "scheduled-task-page" },
    h(Panel, { title: "定时任务", eyebrow: `${(schedules || []).length} Schedules` },
      (schedules || []).length === 0 ? h(EmptyState, { title: "暂无定时任务", text: "创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果" }) :
        h("div", { className: "schedule-card-grid" }, (schedules || []).map((schedule: any) => h("article", { key: schedule.id, className: "schedule-card", "data-testid": `schedule-row-${safeId(schedule.id)}` },
          h("div", { className: "node-card-head" }, h("strong", null, schedule.name || schedule.id), h(StatusBadge, { status: schedule.enabled ? "online" : "warn" }, schedule.enabled ? "enabled" : "disabled")),
          h("code", null, schedule.id),
          h("dl", null,
            h("dt", null, "计划"), h("dd", null, scheduleSpecLabel(schedule.schedule)),
            h("dt", null, "动作"), h("dd", null, scheduleActionLabel(schedule.action)),
            h("dt", null, "下次执行"), h("dd", null, fmtDate(schedule.nextRunAt)),
            h("dt", null, "最近执行"), h("dd", null, schedule.lastRunAt ? `${fmtDate(schedule.lastRunAt)} / ${schedule.lastRunId || "--"}` : "--"),
          ),
          h("div", { className: "dispatch-actions" },
            h("button", { type: "button", className: "ghost-btn", disabled: busy, onClick: () => editSchedule(schedule) }, "编辑"),
            h("button", { type: "button", className: "ghost-btn", disabled: busy, onClick: () => runNow(schedule), "data-testid": `schedule-run-${safeId(schedule.id)}` }, "手动触发"),
            h("button", { type: "button", className: "ghost-btn danger", disabled: busy, onClick: () => deleteSchedule(schedule) }, "删除"),
            h(RawButton, { title: `Schedule ${schedule.id}`, data: schedule, onOpen: onRaw }),
          ),
        ))),
    ),
    h(Panel, { title: form.id ? "配置定时任务" : "新建定时任务", eyebrow: "CRUD" },
      h("form", { className: "dispatch-form schedule-form", onSubmit: save },
        h("label", null, "ID", h("input", { value: form.id, onChange: (event: any) => update("id", event.target.value) })),
        h("label", null, "名称", h("input", { value: form.name, onChange: (event: any) => update("name", event.target.value) })),
        h("label", null, "每日执行时间 UTC", h("input", { value: form.timeOfDay, placeholder: "03:30", onChange: (event: any) => update("timeOfDay", event.target.value) })),
        h("label", null, "启用", h("select", { value: form.enabled ? "true" : "false", onChange: (event: any) => update("enabled", event.target.value === "true") },
          h("option", { value: "true" }, "enabled"),
          h("option", { value: "false" }, "disabled"),
        )),
        h("label", null, "动作类型", h("select", { value: form.actionType, onChange: (event: any) => update("actionType", event.target.value) },
          h("option", { value: "pgdata_backup" }, "PGDATA 备份到百度网盘"),
          h("option", { value: "dispatch" }, "Provider Dispatch"),
        )),
        form.actionType === "pgdata_backup" ? [
          h("label", { key: "remote" }, "网盘根目录", h("input", { value: form.remoteBaseDir, onChange: (event: any) => update("remoteBaseDir", event.target.value) })),
          h("label", { key: "staging" }, "本地 staging 子目录", h("input", { value: form.stagingSubdir, onChange: (event: any) => update("stagingSubdir", event.target.value) })),
        ] : [
          h("label", { key: "provider" }, "Provider", h("select", { value: form.providerId, onChange: (event: any) => update("providerId", event.target.value) },
            (nodes || []).map((node: any) => h("option", { key: node.providerId, value: node.providerId }, `${node.name} / ${node.providerId}`)),
          )),
          h("label", { key: "command" }, "Command", h("select", { value: form.command, onChange: (event: any) => update("command", event.target.value) },
            h("option", { value: "echo" }, "echo"),
            h("option", { value: "docker.ps" }, "docker.ps"),
            h("option", { value: "host.ssh" }, "host.ssh"),
            h("option", { value: "microservice.http" }, "microservice.http"),
          )),
          h("label", { key: "payload", className: "raw-editor-label" }, "Payload JSON", h("textarea", { className: "raw-editor", value: form.payloadJson, onChange: (event: any) => update("payloadJson", event.target.value) })),
        ],
        h("label", null, "超时 ms", h("input", { value: form.timeoutMs, onChange: (event: any) => update("timeoutMs", event.target.value) })),
        h("label", { className: "raw-editor-label" }, "描述", h("textarea", { className: "raw-editor compact", value: form.description, onChange: (event: any) => update("description", event.target.value) })),
        h("div", { className: "dispatch-actions" },
          h("button", { type: "button", className: "ghost-btn", disabled: busy, onClick: () => setForm(defaultScheduleForm(nodes || [])) }, "重置"),
          h("button", { type: "submit", disabled: busy || !form.id }, busy ? "保存中" : "保存任务"),
        ),
        notice ? h("p", { className: "muted paragraph" }, notice) : null,
        h(UniDeskErrorBanner, { error, wide: true }),
      ),
    ),
    h(Panel, { title: "历史执行记录", eyebrow: `${sortedRuns.length} Runs` },
      sortedRuns.length === 0 ? h(EmptyState, { title: "暂无执行记录", text: "定时触发或手动触发后会生成 run history" }) :
        h("div", { className: "table-wrap" }, h("table", { className: "task-history-table schedule-run-table" },
          h("thead", null, h("tr", null, h("th", null, "状态"), h("th", null, "任务"), h("th", null, "触发"), h("th", null, "耗时"), h("th", null, "结果摘要"), h("th", null, "更新时间"), h("th", null, "操作"))),
          h("tbody", null, sortedRuns.map((run: any) => h("tr", { key: run.id, "data-testid": `schedule-run-row-${safeId(run.id)}` },
            h("td", null, h(StatusBadge, { status: scheduleRunTone(run.status) }, run.status)),
            h("td", null, h("strong", null, run.scheduleId), h("code", null, run.id), run.taskId ? h("code", null, run.taskId) : null),
            h("td", null, run.trigger || "--"),
            h("td", null, scheduleRunDuration(run)),
            h("td", null, h(DataSummary, { data: run.result || run.error, empty: "无结果" })),
            h("td", null, fmtDate(run.updatedAt)),
            h("td", null, h(RawButton, { title: `Schedule Run ${run.id}`, data: run, onOpen: onRaw })),
          ))),
        )),
    ),
  );
}

function TopologyPage({ data }: AnyRecord) {
  const overview = data.overview || {};
  return h("div", { className: "page-grid topology-grid" },
    h(Panel, { title: "公开入口", eyebrow: "Public" },
      h("div", { className: "endpoint-list" },
        h("article", null, h("b", null, "Frontend"), h("span", null, cfg.frontendPublicUrl || window.location.origin), h(StatusBadge, { status: "online" }, "public")),
        h("article", null, h("b", null, "Provider Ingress"), h("span", null, cfg.providerIngressPublicUrl || "ws://public/ws/provider"), h(StatusBadge, { status: "online" }, "public")),
      ),
    ),
    h(Panel, { title: "内部服务", eyebrow: "Docker Network Only" },
      h("div", { className: "endpoint-list" },
        h("article", null, h("b", null, "backend-core API"), h("span", null, "http://backend-core:8080"), h(StatusBadge, { status: "internal" }, "internal")),
        h("article", null, h("b", null, "database"), h("span", null, "postgres://database:5432/unidesk"), h(StatusBadge, { status: "internal" }, "internal")),
      ),
    ),
    h(Panel, { title: "运行态", eyebrow: "Runtime" },
      h("div", { className: "metric-grid" },
        h(MetricCard, { label: "DB Ready", value: overview.dbReady ? "YES" : "NO", hint: "internal health" }),
        h(MetricCard, { label: "Online Nodes", value: overview.onlineNodeCount ?? 0, hint: "provider-gateway self-link" }),
      ),
    ),
  );
}

function AuthPage({ session }: AnyRecord) {
  return h(Panel, { title: "认证策略", eyebrow: "Frontend Login" },
    h("div", { className: "policy-grid" },
      h("article", null, h("span", null, "默认账号"), h("strong", null, cfg.authUsername || "admin")),
      h("article", null, h("span", null, "当前会话"), h("strong", null, session?.user?.username || "--")),
      h("article", null, h("span", null, "Session TTL"), h("strong", null, `${cfg.sessionTtlSeconds || 0}s`)),
      h("article", null, h("span", null, "API 访问"), h("strong", null, "同源 Cookie 保护")),
    ),
    h("p", { className: "muted paragraph" }, "浏览器只访问 frontend 同源接口；frontend 容器使用 Docker 内网代理 backend-core API。"),
  );
}

function SecurityPage() {
  return h(Panel, { title: "安全边界", eyebrow: "Exposure Rule" },
    h("div", { className: "security-board" },
      h("article", { className: "allow" }, h("b", null, "允许公网"), h("span", null, "frontend 登录入口"), h("span", null, "provider ingress WebSocket/health")),
      h("article", { className: "deny" }, h("b", null, "禁止公网"), h("span", null, "backend-core REST API"), h("span", null, "PostgreSQL database")),
      h("article", null, h("b", null, "数据库卷"), h("span", null, "named volume unidesk_pgdata_10gb"), h("span", null, "CLI stop/start 不删除数据卷")),
    ),
  );
}

function WorkArea({ activeModule, activeTab, data, session, refresh, onRaw, onNavigate }: AnyRecord) {
  if (activeModule === "ops" && activeTab === "status") return h(OverviewPage, { data, onRaw, onNavigate });
  if (activeModule === "ops" && activeTab === "performance") return h(PerformancePage, { onRaw });
  if (activeModule === "ops" && activeTab === "events") return h(EventsPage, { events: data.events, onRaw });
  if (activeModule === "ops" && activeTab === "logs") return h(LogsPage, { logs: data.logs, onRaw });
  if (activeModule === "nodes" && activeTab === "list") return h(NodeListPage, { nodes: data.nodes, onRaw });
  if (activeModule === "nodes" && activeTab === "monitor") return h(NodeMonitorPage, { nodes: data.nodes, systemStatuses: data.systemStatuses, tasks: data.tasks, onRaw, refresh });
  if (activeModule === "nodes" && activeTab === "docker") return h(DockerStatusPage, { nodes: data.nodes, dockerStatuses: data.dockerStatuses, onRaw });
  if (activeModule === "nodes" && activeTab === "gateway") return h(GatewayVersionPage, { nodes: data.nodes, tasks: data.tasks, onRaw });
  if (activeModule === "nodes" && activeTab === "labels") return h(LabelsPage, { nodes: data.nodes });
  if (activeModule === "nodes" && activeTab === "heartbeats") return h(HeartbeatPage, { nodes: data.nodes });
  if (activeModule === "tasks" && activeTab === "dispatch") return h(DispatchPage, { nodes: data.nodes, onDispatched: refresh, onRaw });
  if (activeModule === "tasks" && activeTab === "scheduled") return h(TaskScheduledPage, { schedules: data.schedules, scheduleRuns: data.scheduleRuns, nodes: data.nodes, refresh, onRaw });
  if (activeModule === "tasks" && activeTab === "pending") return h(TaskPendingPage, { tasks: data.pendingTasks, onRaw });
  if (activeModule === "tasks" && activeTab === "history") return h(TaskHistoryPage, { tasks: data.tasks, onRaw });
  if (activeModule === "tasks" && activeTab === "results") return h(TaskResultsPage, { tasks: data.tasks, onRaw });
  if (activeModule === "apps" && activeTab === "catalog") return h(MicroserviceCatalogPage, { microservices: data.microservices, onRaw, onNavigate });
  if (activeModule === "apps" && activeTab === "hwlab") return h(HwlabPage, {});
  if (activeModule === "apps" && activeTab === "todo-note") return h(TodoNotePage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "findjob") return h(FindJobPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "pipeline") return h(PipelinePage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "met-nonlinear") return h(MetNonlinearPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "claudeqq") return h(ClaudeQqPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "baidu-netdisk") return h(BaiduNetdiskPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "filebrowser") return h(FileBrowserPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "oa-event-flow") return h(OaEventFlowPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "k3sctl") return h(K3sCtlPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl, onNavigate });
  if (activeModule === "apps" && activeTab === "code-queue") return h(CodeQueuePage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl, initialTasksData: initialCodeQueueOverview });
  if (activeModule === "apps" && activeTab === "mdtodo") return h(MdtodoPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "decision-center") return h(DecisionCenterPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "apps" && activeTab === "project-manager") return h(ProjectManagerPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl });
  if (activeModule === "config" && activeTab === "topology") return h(TopologyPage, { data });
  if (activeModule === "config" && activeTab === "auth") return h(AuthPage, { session });
  if (activeModule === "config" && activeTab === "security") return h(SecurityPage);
  return h(EmptyState, { title: "未找到页面", text: "请选择左侧主模块和顶部子功能标签" });
}

function Shell({ session, onLogout }: AnyRecord) {
  const initialRouteTarget = resolveRouteTarget(ROUTE_REGISTRY, window.location.pathname);
  const [activeModule, setActiveModule] = useState(initialRouteTarget.moduleId);
  const [activeTabs, setActiveTabs] = useState({ ...DEFAULT_ACTIVE_TABS, [initialRouteTarget.moduleId]: initialRouteTarget.tabId });
  const [data, setData] = useState({ overview: null, nodes: [], systemStatuses: [], dockerStatuses: [], microservices: [], events: [], tasks: [], pendingTasks: [], schedules: [], scheduleRuns: [], logs: [] });
  const [connection, setConnection] = useState({ ok: false, text: "连接中" });
  const [lastRefresh, setLastRefresh] = useState(null);
  const [clock, setClock] = useState(new Date());
  const [raw, setRaw] = useState(null);
  const [railCollapsed, setRailCollapsed] = useState(false);
  const [refreshing, setRefreshing] = useState(false);
  const refreshInFlightRef = React.useRef(false);

  const module = ROUTE_REGISTRY.moduleById[activeModule] || ROUTE_REGISTRY.modules[0];
  const activeTab = activeTabs[activeModule] || DEFAULT_ACTIVE_TABS[activeModule] || module.tabs[0].id;
  const microservices = Array.isArray(data.microservices) ? data.microservices : [];
  const effectiveMicroservices = microservices.length === 0 && activeModule === "apps" && activeTab === "code-queue"
    ? [fastCodeQueueService]
    : microservices;
  const effectiveData = effectiveMicroservices === microservices ? data : { ...data, microservices: effectiveMicroservices };
  const activeService = activeModule === "apps"
    ? effectiveMicroservices.find((service: any) => String(service?.id || "") === (activeTab === "k3sctl" ? "k3sctl-adapter" : activeTab))
    : null;
  const activeServiceRuntime = activeService ? microserviceRuntime(activeService) : {};
  const activeTabTitle = module.tabs.find((tab: any) => tab.id === activeTab)?.label || activeTab;
  const activeStatusItems = activeService ? [{
    key: "microservice",
    label: "用户服务",
    value: `${activeTabTitle} ${activeServiceRuntime.providerStatus === "online" ? "在线" : activeServiceRuntime.providerStatus || "未知"}`,
    tone: activeServiceRuntime.providerStatus === "online" ? "ok" : "warn",
    testId: "active-microservice-status",
  }] : [];

  async function refresh(): Promise<void> {
    if (refreshInFlightRef.current) return;
    refreshInFlightRef.current = true;
    setRefreshing(true);
    try {
      const requests: Array<[string, Promise<any>]> = [];
      const add = (key: string, path: string): void => {
        requests.push([key, requestJson(path)]);
      };
      const isOverview = activeModule === "ops" && activeTab === "status";
      const needsOverviewSummary = isOverview || (activeModule === "config" && activeTab === "topology");
      const needsNodes = isOverview || activeModule === "nodes" || (activeModule === "tasks" && (activeTab === "dispatch" || activeTab === "scheduled"));
      const needsMicroservices = activeModule === "apps" && activeTab !== "code-queue";
      if (needsOverviewSummary) add("overview", `${cfg.apiBaseUrl}/overview`);
      if (needsNodes) add("nodes", `${cfg.apiBaseUrl}/nodes`);
      if (activeModule === "nodes" && activeTab === "monitor") {
        add("systemStatuses", `${cfg.apiBaseUrl}/nodes/system-status?limit=60`);
        add("tasks", `${cfg.apiBaseUrl}/tasks?limit=120&summary=1`);
      } else if (activeModule === "nodes" && activeTab === "docker") {
        add("dockerStatuses", `${cfg.apiBaseUrl}/nodes/docker-status`);
      } else if (activeModule === "nodes" && activeTab === "gateway") {
        add("tasks", `${cfg.apiBaseUrl}/tasks?limit=300&summary=1`);
      } else if (activeModule === "tasks" && activeTab === "scheduled") {
        add("schedules", `${cfg.apiBaseUrl}/schedules?limit=100`);
        add("scheduleRuns", `${cfg.apiBaseUrl}/schedules/runs?limit=100`);
      } else if (activeModule === "tasks" && activeTab === "pending") {
        add("pendingTasks", `${cfg.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);
      } else if (activeModule === "tasks" && (activeTab === "history" || activeTab === "results")) {
        add("tasks", `${cfg.apiBaseUrl}/tasks?limit=300&summary=1`);
      } else if (isOverview) {
        add("tasks", `${cfg.apiBaseUrl}/tasks?limit=8&lite=1`);
        add("pendingTasks", `${cfg.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);
      }
      if (needsMicroservices) add("microservices", `${cfg.apiBaseUrl}/microservices`);
      if (activeModule === "ops" && activeTab === "events") add("events", `${cfg.apiBaseUrl}/events?limit=100`);
      if (activeModule === "ops" && activeTab === "logs") add("logs", "/logs?limit=100");

      await Promise.all(requests.map(async ([key, promise]) => {
        const value = await promise;
        const patch: AnyRecord = {};
        if (key === "overview") patch.overview = value;
        if (key === "nodes") patch.nodes = value.nodes || [];
        if (key === "systemStatuses") patch.systemStatuses = value.systemStatuses || [];
        if (key === "dockerStatuses") patch.dockerStatuses = value.dockerStatuses || [];
        if (key === "microservices") patch.microservices = value.microservices || [];
        if (key === "events") patch.events = value.events || [];
        if (key === "tasks") patch.tasks = value.tasks || [];
        if (key === "pendingTasks") patch.pendingTasks = value.tasks || [];
        if (key === "schedules") patch.schedules = value.schedules || [];
        if (key === "scheduleRuns") patch.scheduleRuns = value.runs || [];
        if (key === "logs") patch.logs = value.logs || [];
        setData((previous: AnyRecord) => ({ ...previous, ...patch }));
      }));
      setConnection({ ok: true, text: "核心在线" });
      setLastRefresh(new Date());
    } catch (err) {
      setConnection({ ok: false, text: errorMessage(err, "连接失败") });
      if ((err as { status?: number }).status === 401) onLogout(false);
    } finally {
      refreshInFlightRef.current = false;
      setRefreshing(false);
    }
  }

  useEffect(() => {
    const tick = (): void => {
      if (!isDocumentVisible()) return;
      void refresh();
    };
    tick();
    const timer = setInterval(tick, shellRefreshIntervalMs(activeModule, activeTab));
    const onVisible = (): void => {
      if (isDocumentVisible()) tick();
    };
    document.addEventListener("visibilitychange", onVisible);
    return () => {
      clearInterval(timer);
      document.removeEventListener("visibilitychange", onVisible);
    };
  }, [activeModule, activeTab]);

  useEffect(() => {
    const timer = setInterval(() => setClock(new Date()), 1000);
    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    const canonicalPath = canonicalizeKnownRoute(ROUTE_REGISTRY, window.location.pathname);
    if (canonicalPath && window.location.pathname !== canonicalPath) {
      window.history.replaceState(null, "", canonicalPath);
    }
  }, []);

  useEffect(() => {
    const onPopState = (): void => {
      const next = resolveRouteTarget(ROUTE_REGISTRY, window.location.pathname);
      setActiveModule(next.moduleId);
      setActiveTabs((prev: AnyRecord) => ({ ...prev, [next.moduleId]: next.tabId }));
      setRaw(null);
    };
    window.addEventListener("popstate", onPopState);
    return () => window.removeEventListener("popstate", onPopState);
  }, []);

  useEffect(() => {
    window.scrollTo({ top: 0, left: 0, behavior: "auto" });
  }, [activeModule, activeTab]);

  function navigate(moduleId: string, tabId: string, historyMode: "push" | "replace" = "push"): void {
    const safeModule = ROUTE_REGISTRY.moduleById[moduleId] ? moduleId : ROUTE_REGISTRY.fallbackTarget.moduleId;
    const safeTab = ROUTE_REGISTRY.moduleById[safeModule]?.tabs.some((tab: any) => tab.id === tabId)
      ? tabId
      : DEFAULT_ACTIVE_TABS[safeModule] || ROUTE_REGISTRY.moduleById[safeModule]?.tabs[0]?.id || ROUTE_REGISTRY.fallbackTarget.tabId;
    setActiveModule(safeModule);
    setActiveTabs((prev: any) => ({ ...prev, [safeModule]: safeTab }));
    const nextPath = pathForTarget(ROUTE_REGISTRY, safeModule, safeTab);
    if (window.location.pathname !== nextPath) {
      const method = historyMode === "replace" ? "replaceState" : "pushState";
      window.history[method](null, "", nextPath);
    }
  }

  function openRaw(title: string, rawData: any): void {
    setRaw({ title, data: rawData });
  }

  const [notificationOpen, setNotificationOpen] = useState(false);
  const { unreadCount, notifications } = useNotification();
  const latestNotification = notifications.length > 0 ? notifications[notifications.length - 1] : null;

  const devMode = isDevEnvironment(environmentIdentity);
  return h("div", { className: `shell ${railCollapsed ? "rail-collapsed" : ""} ${devMode ? "dev-shell" : ""}`, "data-testid": "app-shell" },
    h(Sidebar, { activeModule, activeTabs, onNavigate: navigate, collapsed: railCollapsed, onToggle: () => setRailCollapsed((value: boolean) => !value) }),
    h("main", { className: "workspace" },
      h(TopBar, { connection, lastRefresh, onRefresh: refresh, onLogout: () => onLogout(true), session, clock, activeStatusItems, onNotificationToggle: () => setNotificationOpen((v: boolean) => !v), unreadCount, environment: environmentIdentity }),
      h(TabBar, { module, activeTab, onNavigate: navigate }),
      h(LoadingContext.Provider, { value: refreshing },
        h(WorkArea, { activeModule, activeTab, data: effectiveData, session, refresh, onRaw: openRaw, onNavigate: navigate }),
      ),
    ),
    h(RawDialog, { raw, onClose: () => setRaw(null) }),
    latestNotification && h(NotificationBanner, { key: latestNotification.id, notification: latestNotification }),
    notificationOpen && h(NotificationPopup, { onClose: () => setNotificationOpen(false) }),
  );
}

function App() {
  const [checking, setChecking] = useState(true);
  const [session, setSession] = useState(null);

  async function loadSession(): Promise<void> {
    setChecking(true);
    try {
      const current = await requestJson("/api/session");
      setSession(current.authenticated ? current : null);
    } catch {
      setSession(null);
    } finally {
      setChecking(false);
    }
  }

  async function logout(callServer: boolean): Promise<void> {
    if (callServer) {
      try { await requestJson("/logout", { method: "POST" }); } catch { /* ignore logout network errors */ }
    }
    setSession(null);
  }

  useEffect(() => { loadSession(); }, []);

  if (checking) return h("main", { className: "loading-screen" }, h("div", { className: "brand-mark" }, "UD"), h("span", null, "加载会话"));
  if (!session) return h(LoginScreen, { onLogin: setSession });
  return h(NotificationProvider, null, h(Shell, { session, onLogout: logout }));
}

const rootElement = document.getElementById("root");
if (rootElement === null) throw new Error("root element not found");
createRoot(rootElement).render(h(App));
