import { createFileRoute } from "@tanstack/react-router";
import {
  Activity,
  AlertTriangle,
  Archive,
  ArrowRight,
  Box,
  Braces,
  Check,
  CheckCircle2,
  CircleStop,
  Clock3,
  CloudUpload,
  Cpu,
  Download,
  FileCode2,
  History,
  LayoutDashboard,
  Package,
  Play,
  RefreshCw,
  RotateCcw,
  Search,
  Server,
  Settings,
  ShieldCheck,
  SquareTerminal,
  X,
  Zap,
} from "lucide-react";
import { FormEvent, ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import {
  BackendEvent,
  BackendRuntime,
  BackendService,
  BackendWitPackage,
  InvokeResult,
  RegisterComponentInput,
  changeRuntimeState,
  changeServiceState,
  fetchSnapshot,
  getApiBase,
  invokeComponent,
  publishWitPackage,
  registerComponent,
  saveApiBase,
  witPackageDownloadUrl,
} from "../api";

type View = "overview" | "services" | "instances" | "wit-packages" | "activity" | "settings";
type ServiceStatus = "running" | "stopped" | "faulted";
type EventTone = "success" | "warning" | "danger" | "neutral";

type Service = {
  id: string;
  revision: string;
  description: string;
  artifact: string;
  status: ServiceStatus;
  updatedAt: string;
  memoryMb: number;
  fuel: string;
  deadlineMs: number;
  mailbox: number;
  maxInputKb: number;
  calls: number;
  errors: number;
  latencyMs: number | null;
};

type RuntimeEvent = {
  id: number;
  time: string;
  title: string;
  detail: string;
  tone: EventTone;
};

type ConnectionState = "connecting" | "online" | "offline";

const NAV_ITEMS: Array<{
  id: View;
  label: string;
  icon: typeof LayoutDashboard;
}> = [
  { id: "overview", label: "运行概览", icon: LayoutDashboard },
  { id: "services", label: "服务版本", icon: Package },
  { id: "instances", label: "运行实例", icon: Server },
  { id: "wit-packages", label: "WIT 包", icon: FileCode2 },
  { id: "activity", label: "调用记录", icon: History },
  { id: "settings", label: "运行设置", icon: Settings },
];

const STATUS_META: Record<ServiceStatus, { label: string; className: string }> = {
  running: { label: "运行中", className: "status-running" },
  stopped: { label: "已停止", className: "status-stopped" },
  faulted: { label: "故障", className: "status-faulted" },
};

function serviceKey(service: Pick<Service, "id" | "revision">) {
  return `${service.id}@${service.revision}`;
}

function toService(service: BackendService): Service {
  return {
    id: service.id,
    revision: service.revision,
    description: "Wasm Component",
    artifact: service.artifact.split(/[\\/]/).pop() ?? service.artifact,
    status: service.status,
    updatedAt: new Date(service.updated_at_ms).toLocaleString("zh-CN", {
      hour12: false,
    }),
    memoryMb: Math.round(service.limits.memory_bytes / 1024 / 1024),
    fuel: compactNumber(service.limits.fuel_per_call),
    deadlineMs: service.limits.deadline_ms,
    mailbox: service.limits.mailbox_capacity,
    maxInputKb: Math.round(service.limits.max_input_bytes / 1024),
    calls: service.calls,
    errors: service.errors,
    latencyMs: service.last_latency_ms,
  };
}

function toEvent(event: BackendEvent): RuntimeEvent {
  const identity =
    event.service_id && event.revision ? `${event.service_id}@${event.revision}` : "Wasmeld";
  const meta: Record<BackendEvent["kind"], { label: string; tone: EventTone }> = {
    registered: { label: "已注册", tone: "success" },
    started: { label: "已启动", tone: "success" },
    stopped: { label: "已停止", tone: "neutral" },
    invoked: { label: "调用完成", tone: "success" },
    failed: { label: "操作失败", tone: "danger" },
  };
  return {
    id: event.id,
    time: new Date(event.timestamp_ms).toLocaleTimeString("zh-CN", {
      hour12: false,
    }),
    title: `${identity} ${meta[event.kind].label}`,
    detail: event.message,
    tone: meta[event.kind].tone,
  };
}

function compactNumber(value: number) {
  if (value >= 1_000_000) return `${value / 1_000_000}M`;
  if (value >= 1_000) return `${value / 1_000}K`;
  return value.toString();
}

function formatDuration(milliseconds: number) {
  const totalSeconds = Math.floor(milliseconds / 1000);
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;
  return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m ${seconds}s`;
}

function formatApiHost(value: string) {
  try {
    return new URL(value).host;
  } catch {
    return value;
  }
}

function parseInvocationInput(value: string, format: "utf8" | "hex") {
  if (format === "utf8") return new TextEncoder().encode(value);
  const compact = value.replace(/\s+/g, "");
  if (compact.length % 2 !== 0 || /[^0-9a-f]/i.test(compact)) {
    throw new Error("HEX 输入必须由成对的十六进制字符组成");
  }
  return Uint8Array.from(compact.match(/.{2}/g)?.map((byte) => Number.parseInt(byte, 16)) ?? []);
}

function invocationInputSize(value: string, format: "utf8" | "hex") {
  try {
    return parseInvocationInput(value, format).byteLength;
  } catch {
    return 0;
  }
}

function formatInvocationOutput(service: Service, output: Uint8Array, format: "utf8" | "hex") {
  if (service.id === "counter" && output.byteLength === 8) {
    return new DataView(output.buffer, output.byteOffset, output.byteLength)
      .getBigUint64(0, true)
      .toString();
  }
  if (format === "hex") {
    return Array.from(output, (byte) => byte.toString(16).padStart(2, "0")).join(" ");
  }
  return new TextDecoder().decode(output) || "(empty)";
}

export const Route = createFileRoute("/")({
  component: Home,
});

function Home() {
  const [view, setView] = useState<View>("overview");
  const [services, setServices] = useState<Service[]>([]);
  const [events, setEvents] = useState<RuntimeEvent[]>([]);
  const [witPackages, setWitPackages] = useState<BackendWitPackage[]>([]);
  const [runtime, setRuntime] = useState<BackendRuntime | null>(null);
  const [runtimeAction, setRuntimeAction] = useState<"start" | "stop" | "restart" | null>(null);
  const [connection, setConnection] = useState<ConnectionState>("connecting");
  const [apiBase, setApiBase] = useState(getApiBase);
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState<"all" | ServiceStatus>("all");
  const [selectedKey, setSelectedKey] = useState("");
  const [deployOpen, setDeployOpen] = useState(false);
  const [witPublishOpen, setWitPublishOpen] = useState(false);
  const [invokeKey, setInvokeKey] = useState<string | null>(null);
  const [toast, setToast] = useState<string | null>(null);

  const selectedService =
    services.find((service) => serviceKey(service) === selectedKey) ?? services[0] ?? null;
  const invokeService = services.find((service) => serviceKey(service) === invokeKey) ?? null;

  const filteredServices = useMemo(() => {
    const normalized = query.trim().toLowerCase();
    return services.filter((service) => {
      const matchesText =
        !normalized ||
        service.id.toLowerCase().includes(normalized) ||
        service.description.toLowerCase().includes(normalized) ||
        service.artifact.toLowerCase().includes(normalized);
      const matchesStatus = statusFilter === "all" || service.status === statusFilter;
      return matchesText && matchesStatus;
    });
  }, [query, services, statusFilter]);

  const filteredWitPackages = useMemo(() => {
    const normalized = query.trim().toLowerCase();
    return witPackages.filter(
      (packageMetadata) =>
        !normalized ||
        packageMetadata.name.toLowerCase().includes(normalized) ||
        packageMetadata.version.toLowerCase().includes(normalized) ||
        packageMetadata.sha256.toLowerCase().includes(normalized),
    );
  }, [query, witPackages]);

  const running = services.filter((service) => service.status === "running").length;
  const faulted = services.filter((service) => service.status === "faulted").length;
  const totalCalls = services.reduce((sum, service) => sum + service.calls, 0);

  const refreshSnapshot = useCallback(async () => {
    try {
      const snapshot = await fetchSnapshot(apiBase);
      const nextServices = snapshot.services.map(toService);
      setServices(nextServices);
      setEvents(snapshot.events.map(toEvent));
      setRuntime(snapshot.runtime);
      setWitPackages(snapshot.witPackages);
      setSelectedKey((current) =>
        nextServices.some((service) => serviceKey(service) === current)
          ? current
          : nextServices[0]
            ? serviceKey(nextServices[0])
            : "",
      );
      setConnection("online");
    } catch {
      setServices([]);
      setEvents([]);
      setRuntime(null);
      setWitPackages([]);
      setConnection("offline");
    }
  }, [apiBase]);

  useEffect(() => {
    void refreshSnapshot();
    const interval = window.setInterval(() => void refreshSnapshot(), 5000);
    return () => window.clearInterval(interval);
  }, [refreshSnapshot]);

  function notify(message: string) {
    setToast(message);
    window.setTimeout(() => setToast(null), 2600);
  }

  async function setServiceStatus(service: Service, status: ServiceStatus) {
    const action =
      status === "stopped" ? "stop" : service.status === "running" ? "restart" : "start";
    try {
      await changeServiceState(apiBase, service, action);
      await refreshSnapshot();
      notify(
        `${service.id} ${
          action === "stop" ? "已停止" : action === "restart" ? "已重启" : "已启动"
        }`,
      );
    } catch (error) {
      notify(error instanceof Error ? error.message : "运行时操作失败");
    }
  }

  async function setRuntimeStatus(action: "start" | "stop" | "restart") {
    setRuntimeAction(action);
    try {
      await changeRuntimeState(apiBase, action);
      await refreshSnapshot();
      notify(
        action === "start"
          ? "Runtime 已启动"
          : action === "stop"
            ? "Runtime 已停止"
            : "Runtime 已重启",
      );
    } catch (error) {
      notify(error instanceof Error ? error.message : "Runtime 操作失败");
    } finally {
      setRuntimeAction(null);
    }
  }

  async function runInvocation(service: Service, input: Uint8Array) {
    const result = await invokeComponent(apiBase, service, input);
    await refreshSnapshot();
    return result;
  }

  async function registerService(input: RegisterComponentInput) {
    const registered = await registerComponent(apiBase, input);
    await refreshSnapshot();
    setSelectedKey(serviceKey(registered));
    setView("services");
    setDeployOpen(false);
    notify("组件注册成功");
  }

  async function publishWit(file: File) {
    const packageMetadata = await publishWitPackage(apiBase, file);
    await refreshSnapshot();
    setWitPublishOpen(false);
    notify(`${packageMetadata.name}@${packageMetadata.version} 已发布`);
  }

  function updateApiBase(value: string) {
    try {
      const nextBase = saveApiBase(value);
      setConnection("connecting");
      setApiBase(nextBase);
      notify("API 地址已保存");
    } catch (error) {
      notify(error instanceof Error ? error.message : "API 地址无效");
    }
  }

  const title = NAV_ITEMS.find((item) => item.id === view)?.label ?? "运行概览";

  return (
    <div className="app-shell">
      <Sidebar
        view={view}
        onChange={setView}
        running={running}
        connection={connection}
        apiBase={apiBase}
        uptimeMs={runtime?.status === "running" ? runtime.uptime_ms : null}
        runtimeStatus={runtime?.status ?? null}
      />

      <div className="app-main">
        <header className="topbar">
          <div className="breadcrumb">
            <span>运行平台</span>
            <ArrowRight size={14} />
            <strong>{title}</strong>
          </div>
          <div className="topbar-actions">
            <label className="global-search">
              <Search size={16} />
              <input
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder="搜索服务或制品"
                aria-label="搜索服务或制品"
              />
            </label>
            <div className={`source-state source-${connection}`} title={`管理 API：${apiBase}`}>
              <span className="source-dot" />
              {connection === "online"
                ? "后端在线"
                : connection === "connecting"
                  ? "连接中"
                  : "后端离线"}
            </div>
            <div className="avatar-button" aria-hidden="true">
              BD
            </div>
          </div>
        </header>

        <main className="content">
          {view === "overview" && (
            <Overview
              services={services}
              filteredServices={filteredServices}
              events={events}
              running={running}
              faulted={faulted}
              totalCalls={totalCalls}
              runtime={runtime}
              selectedService={selectedService}
              onSelect={(service) => setSelectedKey(serviceKey(service))}
              onDeploy={() => setDeployOpen(true)}
              onInvoke={(service) => setInvokeKey(serviceKey(service))}
              onStatus={setServiceStatus}
              onViewAll={() => setView("services")}
              onRefresh={() => void refreshSnapshot()}
              onRuntimeAction={(action) => void setRuntimeStatus(action)}
              runtimeAction={runtimeAction}
            />
          )}

          {view === "services" && (
            <ServicesView
              services={filteredServices}
              statusFilter={statusFilter}
              onFilter={setStatusFilter}
              onDeploy={() => setDeployOpen(true)}
              onInvoke={(service) => setInvokeKey(serviceKey(service))}
              onSelect={(service) => setSelectedKey(serviceKey(service))}
              onStatus={setServiceStatus}
            />
          )}

          {view === "instances" && (
            <InstancesView
              services={services}
              onInvoke={(service) => setInvokeKey(serviceKey(service))}
              onStatus={setServiceStatus}
              onRefresh={() => void refreshSnapshot()}
            />
          )}

          {view === "activity" && <ActivityView events={events} services={services} />}

          {view === "wit-packages" && (
            <WitPackagesView
              apiBase={apiBase}
              packages={filteredWitPackages}
              onPublish={() => setWitPublishOpen(true)}
            />
          )}

          {view === "settings" && (
            <SettingsView endpoint={apiBase} onSaveEndpoint={updateApiBase} />
          )}
        </main>

        <footer className="statusbar">
          <span>
            <ShieldCheck size={14} />
            {connection !== "online"
              ? "等待 Wasmeld"
              : runtime?.status === "running"
                ? "Wasmtime sandbox 正常"
                : "Wasmeld Runtime 已停止"}
          </span>
          <span>Component Model · WASI P2</span>
          <span>Runtime 0.1.0</span>
        </footer>
      </div>

      {deployOpen && (
        <DeployDialog onClose={() => setDeployOpen(false)} onRegister={registerService} />
      )}

      {witPublishOpen && (
        <WitPackageDialog onClose={() => setWitPublishOpen(false)} onPublish={publishWit} />
      )}

      {invokeService && (
        <InvokeDialog
          service={invokeService}
          onClose={() => setInvokeKey(null)}
          onInvoke={runInvocation}
        />
      )}

      {toast && (
        <output className="toast">
          <CheckCircle2 size={17} />
          {toast}
        </output>
      )}
    </div>
  );
}

function Sidebar({
  view,
  onChange,
  running,
  connection,
  apiBase,
  uptimeMs,
  runtimeStatus,
}: {
  view: View;
  onChange: (view: View) => void;
  running: number;
  connection: ConnectionState;
  apiBase: string;
  uptimeMs: number | null;
  runtimeStatus: BackendRuntime["status"] | null;
}) {
  const runtimeLabel =
    connection !== "online"
      ? "离线"
      : runtimeStatus === "running"
        ? "运行中"
        : runtimeStatus === "stopped"
          ? "已停止"
          : "连接中";
  const runtimeHealthClass =
    connection !== "online"
      ? "health-pulse health-offline"
      : runtimeStatus === "running"
        ? "health-pulse"
        : "health-pulse health-stopped";

  return (
    <aside className="sidebar">
      <div className="brand">
        <div className="brand-mark">
          <Braces size={19} strokeWidth={2.2} />
        </div>
        <div>
          <strong>Wasmeld Console</strong>
          <span>Runtime Control</span>
        </div>
      </div>

      <div className="environment-switcher">
        <span className="environment-icon">
          <Server size={15} />
        </span>
        <span>
          <small>环境</small>
          <strong>Local Runtime</strong>
        </span>
      </div>

      <nav className="primary-nav" aria-label="主导航">
        <span className="nav-label">管理</span>
        {NAV_ITEMS.map((item) => {
          const Icon = item.icon;
          return (
            <button
              type="button"
              key={item.id}
              className={view === item.id ? "nav-item active" : "nav-item"}
              onClick={() => onChange(item.id)}
            >
              <Icon size={17} />
              <span>{item.label}</span>
              {item.id === "instances" && running > 0 && (
                <span className="nav-count">{running}</span>
              )}
            </button>
          );
        })}
      </nav>

      <div className="sidebar-runtime">
        <div className="runtime-title">
          <span className={runtimeHealthClass} />
          Runtime {runtimeLabel}
        </div>
        <div className="runtime-meta">
          <span>{formatApiHost(apiBase)}</span>
          <span>{uptimeMs === null ? "—" : formatDuration(uptimeMs)}</span>
        </div>
      </div>
    </aside>
  );
}

function PageHeading({
  eyebrow,
  title,
  description,
  actions,
}: {
  eyebrow: string;
  title: string;
  description: string;
  actions?: ReactNode;
}) {
  return (
    <div className="page-heading">
      <div>
        <span className="eyebrow">{eyebrow}</span>
        <h1>{title}</h1>
        <p>{description}</p>
      </div>
      {actions && <div className="heading-actions">{actions}</div>}
    </div>
  );
}

function Overview({
  services,
  filteredServices,
  events,
  running,
  faulted,
  totalCalls,
  runtime,
  selectedService,
  onSelect,
  onDeploy,
  onInvoke,
  onStatus,
  onViewAll,
  onRefresh,
  onRuntimeAction,
  runtimeAction,
}: {
  services: Service[];
  filteredServices: Service[];
  events: RuntimeEvent[];
  running: number;
  faulted: number;
  totalCalls: number;
  runtime: BackendRuntime | null;
  selectedService: Service | null;
  onSelect: (service: Service) => void;
  onDeploy: () => void;
  onInvoke: (service: Service) => void;
  onStatus: (service: Service, status: ServiceStatus) => void;
  onViewAll: () => void;
  onRefresh: () => void;
  onRuntimeAction: (action: "start" | "stop" | "restart") => void;
  runtimeAction: "start" | "stop" | "restart" | null;
}) {
  const errorCount = services.reduce((sum, service) => sum + service.errors, 0);
  const latencies = services
    .map((service) => service.latencyMs)
    .filter((latency): latency is number => latency !== null);
  const latestLatency = latencies.length ? Math.max(...latencies) : null;

  return (
    <>
      <PageHeading
        eyebrow="LOCAL RUNTIME"
        title="运行概览"
        description={`${services.length} 个已注册版本，${running} 个 Actor 正在运行。`}
        actions={
          <>
            <button
              className="icon-button"
              type="button"
              aria-label="刷新"
              title="刷新"
              onClick={onRefresh}
            >
              <RefreshCw size={17} />
            </button>
            <button className="primary-button" type="button" onClick={onDeploy}>
              <CloudUpload size={17} />
              注册组件
            </button>
          </>
        }
      />

      <section className="metric-grid" aria-label="关键指标">
        <Metric
          icon={<Package size={18} />}
          label="服务版本"
          value={services.length.toString()}
          note="来自 Wasmeld"
          tone="cyan"
        />
        <Metric
          icon={<Activity size={18} />}
          label="运行实例"
          value={running.toString()}
          note={`${services.length - running} 个未运行`}
          tone="green"
        />
        <Metric
          icon={<Zap size={18} />}
          label="累计调用"
          value={totalCalls.toLocaleString("zh-CN")}
          note="持久化统计"
          tone="amber"
        />
        <Metric
          icon={<AlertTriangle size={18} />}
          label="异常"
          value={(faulted + errorCount).toString()}
          note={faulted + errorCount ? "需要检查" : "无异常"}
          tone="coral"
        />
      </section>

      <section className="runtime-band">
        <div className="runtime-band-title">
          <div className="runtime-symbol">
            <Cpu size={18} />
          </div>
          <div>
            <strong>Wasmeld Runtime</strong>
            <span>
              {runtime?.status === "running"
                ? "Engine 已启用 fuel 与 epoch interruption"
                : "Engine 与所有 Actor 已释放"}
            </span>
          </div>
          <div className="runtime-controls" aria-label="Runtime 生命周期">
            {runtime?.status === "stopped" ? (
              <button
                className="icon-button"
                type="button"
                aria-label="启动 Runtime"
                title="启动 Runtime"
                disabled={runtimeAction !== null}
                onClick={() => onRuntimeAction("start")}
              >
                <Play size={15} />
              </button>
            ) : (
              <>
                <button
                  className="icon-button"
                  type="button"
                  aria-label="重启 Runtime"
                  title="重启 Runtime"
                  disabled={runtimeAction !== null || !runtime}
                  onClick={() => onRuntimeAction("restart")}
                >
                  <RotateCcw size={15} />
                </button>
                <button
                  className="icon-button runtime-stop-button"
                  type="button"
                  aria-label="停止 Runtime"
                  title="停止 Runtime"
                  disabled={runtimeAction !== null || !runtime}
                  onClick={() => onRuntimeAction("stop")}
                >
                  <CircleStop size={15} />
                </button>
              </>
            )}
          </div>
        </div>
        <RuntimeStat
          label="已加载版本"
          value={(runtime?.registered_services ?? 0).toString()}
          detail={`${runtime?.managed_services ?? services.length} 个受管制品`}
        />
        <RuntimeStat
          label="活跃 Store"
          value={(runtime?.running_services ?? running).toString()}
          detail="串行 Actor"
        />
        <RuntimeStat
          label="最近延迟"
          value={latestLatency === null ? "—" : `${latestLatency} ms`}
          detail="各服务最近调用"
        />
        <RuntimeStat
          label="运行时间"
          value={runtime?.status === "running" ? formatDuration(runtime.uptime_ms) : "—"}
          detail="当前 Runtime 实例"
        />
      </section>

      <div className="overview-grid">
        <section className="panel service-panel">
          <div className="panel-header">
            <div>
              <h2>服务状态</h2>
              <p>已注册版本及当前 Actor 状态</p>
            </div>
            <button className="text-button" type="button" onClick={onViewAll}>
              查看全部
              <ArrowRight size={15} />
            </button>
          </div>
          <ServiceTable
            services={filteredServices.slice(0, 5)}
            selectedKey={selectedService ? serviceKey(selectedService) : ""}
            onSelect={onSelect}
            onInvoke={onInvoke}
            onStatus={onStatus}
            compact
          />
        </section>

        <aside className="panel event-panel">
          <div className="panel-header">
            <div>
              <h2>实时事件</h2>
              <p>Runtime 生命周期与调用结果</p>
            </div>
            <span className="live-label">
              <span />
              LIVE
            </span>
          </div>
          <EventList events={events.slice(0, 5)} />
        </aside>
      </div>

      {selectedService && (
        <section className="detail-strip">
          <div className="detail-identity">
            <div className="artifact-icon">
              <FileCode2 size={20} />
            </div>
            <div>
              <span>当前选中</span>
              <strong>
                {selectedService.id}
                <small>@{selectedService.revision}</small>
              </strong>
            </div>
          </div>
          <DetailValue label="内存上限" value={`${selectedService.memoryMb} MB`} />
          <DetailValue label="Fuel / 调用" value={selectedService.fuel} />
          <DetailValue label="Deadline" value={`${selectedService.deadlineMs} ms`} />
          <DetailValue label="Mailbox" value={selectedService.mailbox.toString()} />
          <div className="detail-actions">
            <button
              className="secondary-button"
              type="button"
              disabled={selectedService.status !== "running"}
              onClick={() => onInvoke(selectedService)}
            >
              <SquareTerminal size={16} />
              测试调用
            </button>
          </div>
        </section>
      )}
    </>
  );
}

function Metric({
  icon,
  label,
  value,
  note,
  tone,
}: {
  icon: ReactNode;
  label: string;
  value: string;
  note: string;
  tone: string;
}) {
  return (
    <article className="metric">
      <div className={`metric-icon metric-${tone}`}>{icon}</div>
      <div className="metric-copy">
        <span>{label}</span>
        <strong>{value}</strong>
      </div>
      <small>{note}</small>
    </article>
  );
}

function RuntimeStat({ label, value, detail }: { label: string; value: string; detail: string }) {
  return (
    <div className="runtime-stat">
      <span>{label}</span>
      <strong>{value}</strong>
      <small>{detail}</small>
    </div>
  );
}

function DetailValue({ label, value }: { label: string; value: string }) {
  return (
    <div className="detail-value">
      <span>{label}</span>
      <strong>{value}</strong>
    </div>
  );
}

function StatusBadge({ status }: { status: ServiceStatus }) {
  const meta = STATUS_META[status];
  return (
    <span className={`status-badge ${meta.className}`}>
      <span />
      {meta.label}
    </span>
  );
}

function ServiceTable({
  services,
  selectedKey,
  onSelect,
  onInvoke,
  onStatus,
  compact = false,
}: {
  services: Service[];
  selectedKey?: string;
  onSelect: (service: Service) => void;
  onInvoke: (service: Service) => void;
  onStatus: (service: Service, status: ServiceStatus) => void;
  compact?: boolean;
}) {
  if (services.length === 0) {
    return (
      <div className="empty-state">
        <Search size={22} />
        <strong>没有匹配的服务</strong>
        <span>调整搜索关键词或状态筛选。</span>
      </div>
    );
  }

  return (
    <div className="table-scroll">
      <table className="data-table">
        <thead>
          <tr>
            <th>服务</th>
            <th>状态</th>
            {!compact && <th>制品</th>}
            <th>调用</th>
            <th>延迟</th>
            <th>
              <span className="sr-only">操作</span>
            </th>
          </tr>
        </thead>
        <tbody>
          {services.map((service) => (
            <tr
              key={`${service.id}-${service.revision}`}
              className={selectedKey === serviceKey(service) ? "selected" : ""}
            >
              <td>
                <button
                  className="service-cell service-select"
                  type="button"
                  aria-label={`选择 ${service.id}@${service.revision}`}
                  onClick={() => onSelect(service)}
                >
                  <span className="service-glyph">
                    <Box size={16} />
                  </span>
                  <span>
                    <strong>{service.id}</strong>
                    <small>
                      {service.revision} · {service.description}
                    </small>
                  </span>
                </button>
              </td>
              <td>
                <StatusBadge status={service.status} />
              </td>
              {!compact && <td className="artifact-cell">{service.artifact}</td>}
              <td className="numeric-cell">{service.calls.toLocaleString("zh-CN")}</td>
              <td className="numeric-cell">
                {service.latencyMs ? `${service.latencyMs} ms` : "—"}
              </td>
              <td>
                <div className="row-actions">
                  {service.status === "running" ? (
                    <>
                      <button
                        type="button"
                        aria-label={`调用 ${service.id}`}
                        title="测试调用"
                        onClick={() => onInvoke(service)}
                      >
                        <SquareTerminal size={15} />
                      </button>
                      <button
                        type="button"
                        aria-label={`重启 ${service.id}`}
                        title="重启"
                        onClick={() => onStatus(service, "running")}
                      >
                        <RotateCcw size={15} />
                      </button>
                      <button
                        type="button"
                        aria-label={`停止 ${service.id}`}
                        title="停止"
                        onClick={() => onStatus(service, "stopped")}
                      >
                        <CircleStop size={15} />
                      </button>
                    </>
                  ) : (
                    <button
                      type="button"
                      aria-label={`启动 ${service.id}`}
                      title="启动"
                      onClick={() => onStatus(service, "running")}
                    >
                      <Play size={15} />
                    </button>
                  )}
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function EventList({ events }: { events: RuntimeEvent[] }) {
  const icons: Record<EventTone, ReactNode> = {
    success: <Check size={14} />,
    warning: <AlertTriangle size={14} />,
    danger: <X size={14} />,
    neutral: <CircleStop size={14} />,
  };

  return (
    <div className="event-list">
      {events.map((event) => (
        <div className="event-row" key={event.id}>
          <span className={`event-icon event-${event.tone}`}>{icons[event.tone]}</span>
          <div>
            <strong>{event.title}</strong>
            <span>{event.detail}</span>
          </div>
          <time>{event.time}</time>
        </div>
      ))}
    </div>
  );
}

function ServicesView({
  services,
  statusFilter,
  onFilter,
  onDeploy,
  onInvoke,
  onSelect,
  onStatus,
}: {
  services: Service[];
  statusFilter: "all" | ServiceStatus;
  onFilter: (status: "all" | ServiceStatus) => void;
  onDeploy: () => void;
  onInvoke: (service: Service) => void;
  onSelect: (service: Service) => void;
  onStatus: (service: Service, status: ServiceStatus) => void;
}) {
  return (
    <>
      <PageHeading
        eyebrow="REGISTRY"
        title="服务版本"
        description="管理 Runtime 已注册的不可变 Wasm Component 制品。"
        actions={
          <button className="primary-button" type="button" onClick={onDeploy}>
            <CloudUpload size={17} />
            注册组件
          </button>
        }
      />
      <section className="panel full-panel">
        <div className="filterbar">
          <div className="segmented" aria-label="状态筛选">
            {[
              ["all", "全部"],
              ["running", "运行中"],
              ["stopped", "已停止"],
              ["faulted", "故障"],
            ].map(([value, label]) => (
              <button
                type="button"
                key={value}
                className={statusFilter === value ? "active" : ""}
                onClick={() => onFilter(value as "all" | ServiceStatus)}
              >
                {label}
              </button>
            ))}
          </div>
          <span className="result-count">{services.length} 个版本</span>
        </div>
        <ServiceTable
          services={services}
          onSelect={onSelect}
          onInvoke={onInvoke}
          onStatus={onStatus}
        />
      </section>
    </>
  );
}

function WitPackagesView({
  apiBase,
  packages,
  onPublish,
}: {
  apiBase: string;
  packages: BackendWitPackage[];
  onPublish: () => void;
}) {
  function downloadPackage(packageMetadata: BackendWitPackage) {
    const anchor = document.createElement("a");
    anchor.href = witPackageDownloadUrl(apiBase, packageMetadata);
    anchor.download = `${packageMetadata.name.replace(":", "-")}-${packageMetadata.version}.wasm`;
    document.body.append(anchor);
    anchor.click();
    anchor.remove();
  }

  return (
    <>
      <PageHeading
        eyebrow="WIT REGISTRY"
        title="WIT 包"
        description="管理组件开发所依赖的不可变、版本化 WIT Package。"
        actions={
          <button className="primary-button" type="button" onClick={onPublish}>
            <CloudUpload size={17} />
            发布 WIT 包
          </button>
        }
      />
      <section className="panel full-panel">
        <div className="filterbar">
          <span className="registry-note">发布后不可覆盖；包名、版本与依赖由制品自动解析。</span>
          <span className="result-count">{packages.length} 个包版本</span>
        </div>
        {packages.length === 0 ? (
          <div className="empty-state">
            <FileCode2 size={22} />
            <strong>没有匹配的 WIT 包</strong>
            <span>发布二进制 WIT Package，或调整搜索关键词。</span>
          </div>
        ) : (
          <div className="table-scroll">
            <table className="data-table wit-package-table">
              <thead>
                <tr>
                  <th>Package</th>
                  <th>依赖</th>
                  <th>SHA-256</th>
                  <th>
                    <span className="sr-only">操作</span>
                  </th>
                </tr>
              </thead>
              <tbody>
                {packages.map((packageMetadata) => {
                  const dependencies = packageMetadata.dependencies
                    .map((dependency) => `${dependency.name}@${dependency.version}`)
                    .join(", ");
                  return (
                    <tr key={`${packageMetadata.name}@${packageMetadata.version}`}>
                      <td aria-label={`${packageMetadata.name}@${packageMetadata.version}`}>
                        <div className="service-cell">
                          <span className="service-glyph">
                            <FileCode2 size={16} />
                          </span>
                          <span>
                            <strong>{packageMetadata.name}</strong>
                            <small>{packageMetadata.version}</small>
                          </span>
                        </div>
                      </td>
                      <td className="artifact-cell" title={dependencies || "无直接依赖"}>
                        {dependencies || "无直接依赖"}
                      </td>
                      <td className="artifact-cell" title={packageMetadata.sha256}>
                        {packageMetadata.sha256}
                      </td>
                      <td>
                        <div className="row-actions">
                          <button
                            type="button"
                            title="下载 WIT 包"
                            aria-label={`下载 ${packageMetadata.name}@${packageMetadata.version}`}
                            onClick={() => downloadPackage(packageMetadata)}
                          >
                            <Download size={15} />
                          </button>
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </section>
    </>
  );
}

function InstancesView({
  services,
  onInvoke,
  onStatus,
  onRefresh,
}: {
  services: Service[];
  onInvoke: (service: Service) => void;
  onStatus: (service: Service, status: ServiceStatus) => void;
  onRefresh: () => void;
}) {
  const instances = services.filter(
    (service) => service.status === "running" || service.status === "faulted",
  );

  return (
    <>
      <PageHeading
        eyebrow="ACTORS"
        title="运行实例"
        description={`${instances.length} 个 Actor 保持独立 Store 与 Instance。`}
        actions={
          <button
            className="icon-button"
            type="button"
            title="刷新"
            aria-label="刷新"
            onClick={onRefresh}
          >
            <RefreshCw size={17} />
          </button>
        }
      />
      <section className="instance-list">
        {instances.length === 0 ? (
          <output className="instance-placeholder">
            <div className="instance-placeholder-icon">
              <Cpu size={22} />
            </div>
            <strong>暂无运行实例</strong>
            <span>0 ACTIVE ACTORS</span>
          </output>
        ) : (
          instances.map((service) => (
            <article className="instance-row" key={service.id}>
              <div className="instance-main">
                <span className={`instance-indicator ${service.status}`} />
                <div className="artifact-icon">
                  <Cpu size={19} />
                </div>
                <div>
                  <strong>
                    {service.id}@{service.revision}
                  </strong>
                  <span>actor/{service.id}-01</span>
                </div>
              </div>
              <DetailValue
                label="Store 内存"
                value={
                  service.status === "running"
                    ? `${Math.round(service.memoryMb * 0.42)} MB`
                    : "已释放"
                }
              />
              <DetailValue label="调用总数" value={service.calls.toLocaleString("zh-CN")} />
              <DetailValue
                label="最近延迟"
                value={service.latencyMs ? `${service.latencyMs} ms` : "—"}
              />
              <div className="instance-status">
                <StatusBadge status={service.status} />
                <span>{service.updatedAt}</span>
              </div>
              <div className="row-actions">
                <button
                  type="button"
                  title="测试调用"
                  aria-label={`调用 ${service.id}`}
                  disabled={service.status !== "running"}
                  onClick={() => onInvoke(service)}
                >
                  <SquareTerminal size={16} />
                </button>
                <button
                  type="button"
                  title="重启"
                  aria-label={`重启 ${service.id}`}
                  onClick={() => onStatus(service, "running")}
                >
                  <RotateCcw size={16} />
                </button>
                <button
                  type="button"
                  title="停止"
                  aria-label={`停止 ${service.id}`}
                  disabled={service.status !== "running"}
                  onClick={() => onStatus(service, "stopped")}
                >
                  <CircleStop size={16} />
                </button>
              </div>
            </article>
          ))
        )}
      </section>
    </>
  );
}

function ActivityView({ events, services }: { events: RuntimeEvent[]; services: Service[] }) {
  const calls = services.reduce((sum, service) => sum + service.calls, 0);
  const errors = services.reduce((sum, service) => sum + service.errors, 0);
  const latencies = services
    .map((service) => service.latencyMs)
    .filter((latency): latency is number => latency !== null);
  const averageLatency = latencies.length
    ? latencies.reduce((sum, latency) => sum + latency, 0) / latencies.length
    : null;

  function exportEvents() {
    const blob = new Blob([JSON.stringify(events, null, 2)], {
      type: "application/json",
    });
    const url = URL.createObjectURL(blob);
    const anchor = document.createElement("a");
    anchor.href = url;
    anchor.download = "wasmeld-events.json";
    anchor.click();
    URL.revokeObjectURL(url);
  }

  return (
    <>
      <PageHeading
        eyebrow="EVENT STREAM"
        title="调用记录"
        description="Runtime 生命周期、调用结果与沙箱拒绝记录。"
        actions={
          <button className="secondary-button" type="button" onClick={exportEvents}>
            <Archive size={16} />
            导出记录
          </button>
        }
      />
      <section className="panel full-panel">
        <div className="activity-summary">
          <div>
            <span>时间范围</span>
            <strong>当前进程</strong>
          </div>
          <div>
            <span>成功率</span>
            <strong>{calls ? `${(((calls - errors) / calls) * 100).toFixed(2)}%` : "—"}</strong>
          </div>
          <div>
            <span>平均延迟</span>
            <strong>{averageLatency === null ? "—" : `${averageLatency.toFixed(1)} ms`}</strong>
          </div>
          <div>
            <span>记录数</span>
            <strong>{events.length}</strong>
          </div>
        </div>
        <EventList events={events} />
      </section>
    </>
  );
}

function SettingsView({
  endpoint,
  onSaveEndpoint,
}: {
  endpoint: string;
  onSaveEndpoint: (value: string) => void;
}) {
  const [value, setValue] = useState(endpoint);

  return (
    <>
      <PageHeading
        eyebrow="CONFIGURATION"
        title="运行设置"
        description="本地控制台连接与 Runtime 默认参数。"
      />
      <form
        className="settings-form"
        onSubmit={(event) => {
          event.preventDefault();
          onSaveEndpoint(value);
        }}
      >
        <section className="settings-section">
          <div className="settings-heading">
            <Server size={18} />
            <div>
              <h2>控制端连接</h2>
              <p>管理 API 的本地访问地址。</p>
            </div>
          </div>
          <div className="form-field wide-field">
            <label htmlFor="endpoint">API 地址</label>
            <input id="endpoint" value={value} onChange={(event) => setValue(event.target.value)} />
            <span>连接状态将在顶部工具栏显示。</span>
          </div>
        </section>

        <div className="form-footer">
          <button className="primary-button" type="submit">
            保存设置
          </button>
        </div>
      </form>
    </>
  );
}

function DialogFrame({
  title,
  description,
  icon,
  onClose,
  children,
}: {
  title: string;
  description: string;
  icon: ReactNode;
  onClose: () => void;
  children: ReactNode;
}) {
  return (
    <div className="dialog-backdrop">
      <dialog
        open
        className="dialog"
        aria-label={title}
        onCancel={onClose}
        onKeyDown={(event) => {
          if (event.key === "Escape") onClose();
        }}
      >
        <div className="dialog-header">
          <div className="dialog-title">
            <span>{icon}</span>
            <div>
              <h2>{title}</h2>
              <p>{description}</p>
            </div>
          </div>
          <button
            className="icon-button"
            type="button"
            aria-label="关闭"
            title="关闭"
            onClick={onClose}
          >
            <X size={18} />
          </button>
        </div>
        {children}
      </dialog>
    </div>
  );
}

function DeployDialog({
  onClose,
  onRegister,
}: {
  onClose: () => void;
  onRegister: (input: RegisterComponentInput) => Promise<void>;
}) {
  const [file, setFile] = useState<File | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");
  const fileName = file?.name ?? "";

  async function submit(event: FormEvent) {
    event.preventDefault();
    if (!file) return;
    if (!file.name.toLowerCase().endsWith(".wasmpkg")) {
      setError("请选择 .wasmpkg 组件包");
      return;
    }
    setSubmitting(true);
    setError("");
    try {
      await onRegister({ file });
    } catch (submitError) {
      setError(submitError instanceof Error ? submitError.message : "组件注册失败");
      setSubmitting(false);
    }
  }

  return (
    <DialogFrame
      title="注册组件包"
      description="组件元数据与运行边界由平台自动校验。"
      icon={<CloudUpload size={19} />}
      onClose={onClose}
    >
      <form className="dialog-form" onSubmit={submit}>
        <label className={fileName ? "upload-zone has-file" : "upload-zone"}>
          <input
            type="file"
            accept=".wasmpkg,application/zip,application/vnd.wasm.component-package"
            onChange={(event) => {
              setFile(event.target.files?.[0] ?? null);
              setError("");
            }}
          />
          {fileName ? <Package size={28} /> : <CloudUpload size={28} />}
          <strong>{fileName || "选择组件包"}</strong>
          <span>
            {file
              ? `${(file.size / 1024 / 1024).toFixed(2)} MB · 等待校验`
              : ".wasmpkg · 最大 64 MB"}
          </span>
        </label>

        {error && <div className="form-error">{error}</div>}

        <div className="dialog-footer">
          <button className="secondary-button" type="button" onClick={onClose}>
            取消
          </button>
          <button className="primary-button" type="submit" disabled={submitting || !fileName}>
            {submitting ? <RefreshCw className="spin" size={16} /> : <ShieldCheck size={16} />}
            {submitting ? "正在注册" : "校验并注册"}
          </button>
        </div>
      </form>
    </DialogFrame>
  );
}

function WitPackageDialog({
  onClose,
  onPublish,
}: {
  onClose: () => void;
  onPublish: (file: File) => Promise<void>;
}) {
  const [file, setFile] = useState<File | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");
  const fileName = file?.name ?? "";

  async function submit(event: FormEvent) {
    event.preventDefault();
    if (!file) return;
    if (!file.name.toLowerCase().endsWith(".wasm")) {
      setError("请选择由 wasmeld wit build 生成的 .wasm 文件");
      return;
    }
    if (file.size > 4 * 1024 * 1024) {
      setError("WIT 包不能超过 4 MB");
      return;
    }
    setSubmitting(true);
    setError("");
    try {
      await onPublish(file);
    } catch (submitError) {
      setError(submitError instanceof Error ? submitError.message : "WIT 包发布失败");
      setSubmitting(false);
    }
  }

  return (
    <DialogFrame
      title="发布 WIT 包"
      description="包名、语义版本和直接依赖将从二进制 WIT Package 读取。"
      icon={<FileCode2 size={19} />}
      onClose={onClose}
    >
      <form className="dialog-form" onSubmit={submit}>
        <label className={fileName ? "upload-zone has-file" : "upload-zone"}>
          <input
            type="file"
            accept=".wasm,application/wasm"
            onChange={(event) => {
              setFile(event.target.files?.[0] ?? null);
              setError("");
            }}
          />
          {fileName ? <FileCode2 size={28} /> : <CloudUpload size={28} />}
          <strong>{fileName || "选择二进制 WIT Package"}</strong>
          <span>
            {file ? `${(file.size / 1024).toFixed(1)} KB · 等待校验` : ".wasm · 最大 4 MB"}
          </span>
        </label>

        {error && <div className="form-error">{error}</div>}

        <div className="dialog-footer">
          <button className="secondary-button" type="button" onClick={onClose}>
            取消
          </button>
          <button className="primary-button" type="submit" disabled={submitting || !fileName}>
            {submitting ? <RefreshCw className="spin" size={16} /> : <ShieldCheck size={16} />}
            {submitting ? "正在发布" : "校验并发布"}
          </button>
        </div>
      </form>
    </DialogFrame>
  );
}

function InvokeDialog({
  service,
  onClose,
  onInvoke,
}: {
  service: Service;
  onClose: () => void;
  onInvoke: (service: Service, input: Uint8Array) => Promise<InvokeResult>;
}) {
  const [input, setInput] = useState(service.id === "echo" ? "hello wasm" : "");
  const [format, setFormat] = useState<"utf8" | "hex">("utf8");
  const [output, setOutput] = useState("");
  const [running, setRunning] = useState(false);
  const [failed, setFailed] = useState(false);
  const [latency, setLatency] = useState<number | null>(null);

  async function invoke() {
    setRunning(true);
    setOutput("");
    setFailed(false);
    setLatency(null);
    try {
      const result = await onInvoke(service, parseInvocationInput(input, format));
      setOutput(formatInvocationOutput(service, result.output, format));
      setLatency(result.latencyMs);
    } catch (invokeError) {
      setFailed(true);
      setOutput(invokeError instanceof Error ? invokeError.message : "组件调用失败");
    } finally {
      setRunning(false);
    }
  }

  return (
    <DialogFrame
      title={`调用 ${service.id}@${service.revision}`}
      description="请求将进入该实例的串行 mailbox。"
      icon={<SquareTerminal size={19} />}
      onClose={onClose}
    >
      <div className="invoke-body">
        <div className="invoke-toolbar">
          <div className="segmented">
            <button
              type="button"
              className={format === "utf8" ? "active" : ""}
              onClick={() => setFormat("utf8")}
            >
              UTF-8
            </button>
            <button
              type="button"
              className={format === "hex" ? "active" : ""}
              onClick={() => setFormat("hex")}
            >
              HEX
            </button>
          </div>
          <span>{invocationInputSize(input, format)} B</span>
        </div>
        <label className="code-field">
          <span>输入</span>
          <textarea
            value={input}
            onChange={(event) => setInput(event.target.value)}
            spellCheck={false}
            placeholder={format === "utf8" ? "输入请求内容" : "00 ff a1"}
          />
        </label>

        <div className={failed ? "invoke-output failed" : "invoke-output"}>
          <div>
            <span>输出</span>
            {output && latency !== null && (
              <small>
                <Clock3 size={13} />
                {latency} ms
              </small>
            )}
          </div>
          <pre>{running ? "invoking..." : output || "等待调用"}</pre>
        </div>
      </div>
      <div className="dialog-footer">
        <button className="secondary-button" type="button" onClick={onClose}>
          关闭
        </button>
        <button className="primary-button" type="button" disabled={running} onClick={invoke}>
          {running ? <RefreshCw className="spin" size={16} /> : <Play size={16} />}
          执行调用
        </button>
      </div>
    </DialogFrame>
  );
}
