// SPEC: PJ2026-010405 云端控制台。
// Implementation reference: draft-2026-07-13-p0-cloud-console。
// Responsibility: 保存 HWPOD typed topology 的最近成功快照，并投影刷新、部分失败与 stale 状态。

import { ref } from "vue";
import { defineStore } from "pinia";
import { hwpodAPI } from "@/api";
import type { TopologyQuery } from "@/api/hwpod";
import type {
  HwpodDeviceTopologyItem,
  HwpodNodeOpsResponse,
  HwpodNodeTopologyItem,
  HwpodOperationResponse,
  HwpodSpecsResponse,
  HwpodTopologyResponse,
  HwlabNodeUpdateMetadata
} from "@/types";

export const useHwpodStore = defineStore("hwpod", () => {
  const specs = ref<HwpodSpecsResponse | null>(null);
  const nodeOps = ref<HwpodNodeOpsResponse | null>(null);
  const loading = ref(false);
  const error = ref<string | null>(null);
  const deviceTopology = ref<HwpodTopologyResponse<HwpodDeviceTopologyItem> | null>(null);
  const nodeTopology = ref<HwpodTopologyResponse<HwpodNodeTopologyItem> | null>(null);
  const nodeUpdate = ref<HwlabNodeUpdateMetadata | null>(null);
  const consoleLoading = ref(false);
  const consoleError = ref<string | null>(null);
  const consoleStale = ref(false);
  let consoleRequestId = 0;
  const lastOperation = ref<HwpodOperationResponse | null>(null);
  const operationError = ref<string | null>(null);

  async function refresh(): Promise<void> {
    loading.value = true;
    error.value = null;
    const [specsResult, nodeOpsResult] = await Promise.all([hwpodAPI.specs(), hwpodAPI.nodeOpsHealth()]);
    specs.value = specsResult.data;
    nodeOps.value = nodeOpsResult.data;
    error.value = specsResult.ok && nodeOpsResult.ok ? null : specsResult.error ?? nodeOpsResult.error ?? "HWPOD API unavailable";
    loading.value = false;
  }

  async function refreshConsole(resource: "device" | "node" | "onboarding", query: TopologyQuery = {}): Promise<void> {
    const requestId = ++consoleRequestId;
    consoleLoading.value = true;
    consoleError.value = null;
    consoleStale.value = false;
    try {
      if (resource === "device") {
        const result = await hwpodAPI.devices(query);
        if (requestId !== consoleRequestId) return;
        if (result.ok && result.data) deviceTopology.value = result.data;
        else {
          consoleError.value = result.error ?? "HWPOD 设备拓扑不可用";
          consoleStale.value = Boolean(deviceTopology.value);
        }
      } else if (resource === "node") {
        const result = await hwpodAPI.nodes(query);
        if (requestId !== consoleRequestId) return;
        if (result.ok && result.data) nodeTopology.value = result.data;
        else {
          consoleError.value = result.error ?? "HWPOD Node 拓扑不可用";
          consoleStale.value = Boolean(nodeTopology.value);
        }
      } else {
        const [nodesResult, updateResult] = await Promise.all([hwpodAPI.nodes(query), hwpodAPI.nodeUpdate()]);
        if (requestId !== consoleRequestId) return;
        if (nodesResult.ok && nodesResult.data) nodeTopology.value = nodesResult.data;
        if (updateResult.ok && updateResult.data) nodeUpdate.value = updateResult.data;
        if (!nodesResult.ok || !updateResult.ok) {
          consoleError.value = nodesResult.error ?? updateResult.error ?? "节点接入元数据不可用";
          consoleStale.value = Boolean(nodeTopology.value || nodeUpdate.value);
        }
      }
    } catch (cause) {
      if (requestId !== consoleRequestId) return;
      consoleError.value = cause instanceof Error ? cause.message : "HWPOD 控制台刷新失败";
      consoleStale.value = resource === "device" ? Boolean(deviceTopology.value) : resource === "node" ? Boolean(nodeTopology.value) : Boolean(nodeTopology.value || nodeUpdate.value);
    } finally {
      if (requestId === consoleRequestId) consoleLoading.value = false;
    }
  }

  async function executeOperation(hwpodId: string, intent: string, args: Record<string, unknown> = {}, timeoutMs = 60_000): Promise<HwpodOperationResponse> {
    operationError.value = null;
    const submitted = await hwpodAPI.startOperation({ hwpodId, intent, args });
    if (!submitted.ok || !submitted.data?.operationId) throw operationFailure(submitted.error ?? "HWPOD operation 提交失败");
    lastOperation.value = submitted.data;
    const deadline = Date.now() + timeoutMs;
    while (Date.now() < deadline) {
      await delay(500);
      const status = await hwpodAPI.operation(submitted.data.operationId);
      if (!status.ok || !status.data) throw operationFailure(status.error ?? "HWPOD operation 状态查询失败");
      lastOperation.value = status.data;
      if (isTerminal(status.data.status)) return status.data;
    }
    throw operationFailure(`HWPOD operation ${submitted.data.operationId} 在 ${timeoutMs}ms 内未终止`);
  }

  function operationFailure(message: string): Error {
    operationError.value = message;
    return new Error(message);
  }

  return { specs, nodeOps, loading, error, refresh, deviceTopology, nodeTopology, nodeUpdate, consoleLoading, consoleError, consoleStale, refreshConsole, lastOperation, operationError, executeOperation };
});

function isTerminal(status: string): boolean { return /completed|failed|canceled|terminated|timed.?out/u.test(status); }
function delay(ms: number): Promise<void> { return new Promise((resolve) => window.setTimeout(resolve, ms)); }
