import assert from "node:assert/strict";
import { test } from "bun:test";

import { createCloudApiServer } from "./server.ts";
import { DASHBOARD_SUMMARY_CONTRACT_VERSION } from "./server-dashboard-http.ts";

test("dashboard summary returns one typed bounded read model from real domain contracts", async () => {
  const sessionToken = "hws_dashboard_contract_secret";
  const requestedNavIds: string[] = [];
  const auth = {
    ok: true,
    actor: { id: "usr_dashboard", username: "operator", displayName: "控制台操作员", role: "admin" },
    authMethod: "user-billing-session",
    session: { id: "ses_dashboard" },
    userBilling: { active: true, token: sessionToken, valuesRedacted: true }
  };
  const userBillingClient = {
    configured: true,
    async billingSummary(token: string, options: { limit: number }) {
      assert.equal(token, sessionToken);
      assert.deepEqual(options, { limit: 5 });
      return {
        ok: true,
        status: 200,
        body: {
          contractVersion: "user-billing-summary-v1",
          status: "ready",
          planId: "plan_team",
          plan: { id: "plan_team", displayName: "Team", status: "active" },
          credits: { balance: 240, reserved: 20, available: 220 },
          entitlements: [{ resourceType: "code-agent" }, { resourceType: "hwpod" }],
          reservations: { activeCount: 1 }
        }
      };
    }
  };
  const server = createCloudApiServer({
    env: { HWLAB_PROJECT_MANAGEMENT_URL: "http://project-management.test", HWLAB_WORKBENCH_EMPTY_SESSION_GC_ENABLED: "0" },
    accessController: dashboardAccessController(auth, userBillingClient, requestedNavIds),
    userBillingClient,
    hwpodNodeWsRegistry: dashboardHwpodRegistry(),
    dashboardDiscoverHwpodSpecs: async () => [dashboardHwpodSpec()],
    dashboardNow: () => "2026-07-13T12:00:00.000Z",
    fetchImpl: async (input: URL | RequestInfo) => projectManagementResponse(new URL(String(input))),
    kafkaEventBridge: disabledKafkaBridge()
  });
  await listen(server);

  try {
    const response = await fetch(`http://127.0.0.1:${(server.address() as any).port}/v1/dashboard/summary`);
    assert.equal(response.status, 200);
    const body = await response.json();
    assert.equal(body.contractVersion, DASHBOARD_SUMMARY_CONTRACT_VERSION);
    assert.equal(body.route, "/v1/dashboard/summary");
    assert.equal(body.status, "ready");
    assert.equal(body.actor.id, "usr_dashboard");
    assert.deepEqual(body.sources.map((source: any) => [source.id, source.state]), [["work", "ready"], ["hwpod", "ready"], ["billing", "ready"]]);
    assert.equal(body.work.projectCount, 2);
    assert.deepEqual(body.work.taskCounts, { open: 2, inProgress: 1, blocked: 1 });
    assert.deepEqual(body.work.continuations.map((task: any) => task.taskId), ["R2", "R1"]);
    assert.equal(body.work.continuations[0].href, "/projects/mdtodo/sources/source-main/files/file-main/tasks/R2");
    assert.equal(body.hwpod.nodeCount, 1);
    assert.equal(body.hwpod.onlineNodeCount, 1);
    assert.equal(body.hwpod.availableDeviceCount, 1);
    assert.deepEqual(body.billing.plan, { id: "plan_team", displayName: "Team", status: "active" });
    assert.deepEqual(body.billing.credits, { balance: 240, reserved: 20, available: 220 });
    assert.equal(body.billing.entitlementCount, 2);
    assert.equal(body.billing.activeReservationCount, 1);
    assert.equal(body.issues.some((issue: any) => issue.code === "mdtodo_tasks_blocked" && issue.count === 1), true);
    assert.equal(JSON.stringify(body).includes(sessionToken), false);
    assert.equal(body.valuesRedacted, true);
    assert.equal(requestedNavIds.includes("user.dashboard"), true);
  } finally {
    await close(server);
  }
});

test("dashboard summary keeps successful sections when upstreams are partial, stale, or restricted", async () => {
  const auth = {
    ok: true,
    actor: { id: "usr_dashboard_partial", username: "member", role: "user" },
    authMethod: "user-billing-session",
    session: { id: "ses_dashboard_partial" },
    userBilling: { active: true, token: "hws_dashboard_partial", valuesRedacted: true }
  };
  const userBillingClient = {
    configured: true,
    async billingSummary() {
      return { ok: true, status: 200, body: { status: "stale", observedAt: "2026-07-12T12:00:00.000Z", planId: "default", credits: { available: 8 } } };
    }
  };
  const requestedNavIds: string[] = [];
  const accessController = dashboardAccessController(auth, userBillingClient, requestedNavIds, (navId) => navId !== "admin.hwpodGroups");
  const server = createCloudApiServer({
    env: { HWLAB_PROJECT_MANAGEMENT_URL: "http://project-management.test", HWLAB_WORKBENCH_EMPTY_SESSION_GC_ENABLED: "0" },
    accessController,
    userBillingClient,
    hwpodNodeWsRegistry: dashboardHwpodRegistry(),
    dashboardDiscoverHwpodSpecs: async () => { throw new Error("restricted HWPOD discovery must not run"); },
    dashboardNow: () => "2026-07-13T12:00:00.000Z",
    fetchImpl: async (input: URL | RequestInfo) => {
      const url = new URL(String(input));
      if (url.searchParams.get("status") === "in_progress") return jsonResponse(503, { ok: false, error: { code: "projection_refreshing" } });
      return projectManagementResponse(url);
    },
    kafkaEventBridge: disabledKafkaBridge()
  });
  await listen(server);

  try {
    const response = await fetch(`http://127.0.0.1:${(server.address() as any).port}/v1/dashboard/summary`);
    assert.equal(response.status, 200);
    const body = await response.json();
    assert.equal(body.status, "partial");
    assert.equal(body.work.state, "partial");
    assert.equal(body.work.projectCount, 2);
    assert.equal(body.work.taskCounts.inProgress, null);
    assert.equal(body.hwpod.state, "restricted");
    assert.equal(body.hwpod.nodeCount, null);
    assert.equal(body.billing.state, "stale");
    assert.equal(body.billing.credits.available, 8);
    assert.equal(body.issues.some((issue: any) => issue.code === "work_summary_partial"), true);
    assert.equal(body.issues.some((issue: any) => issue.code === "billing_summary_stale"), true);
    assert.equal(body.issues.some((issue: any) => issue.domain === "hwpod"), false);
    assert.equal(body.sources.find((source: any) => source.id === "hwpod").reason, "当前身份无 HWPOD topology 访问权限");
    assert.equal(requestedNavIds.includes("user.dashboard"), true);
  } finally {
    await close(server);
  }
});

function dashboardAccessController(auth: any, userBilling: any, requestedNavIds: string[], allow: (navId: string) => boolean = () => true) {
  return {
    required: true,
    userBilling,
    async requireNavAccess(_request: unknown, _response: unknown, navId: string) {
      requestedNavIds.push(navId);
      return allow(navId) ? auth : null;
    },
    async authenticate() { return auth; },
    navAccessAllowed(_actor: unknown, navId: string) { return allow(navId); }
  };
}

function projectManagementResponse(url: URL) {
  if (url.pathname === "/v1/project-management/projects") {
    return jsonResponse(200, { ok: true, contractVersion: "project-management-v1", projects: [{ projectId: "project_alpha", name: "Alpha", status: "active" }, { projectId: "project_beta", name: "Beta", status: "ready" }] });
  }
  if (url.pathname === "/v1/project-management/mdtodo/tasks") {
    const status = url.searchParams.get("status");
    const task = (taskId: string, taskStatus: string) => ({ taskRef: `mdtodo:source-main:file-main:${taskId}`, taskId, title: `Task ${taskId}`, status: taskStatus, projectId: "project_alpha", sourceId: "source-main", fileRef: "file-main", updatedAt: "2026-07-13T10:00:00.000Z" });
    if (status === "in_progress") return jsonResponse(200, { ok: true, tasks: [task("R2", status)], page: { offset: 0, limit: 6, total: 1, hasMore: false } });
    if (status === "open") return jsonResponse(200, { ok: true, tasks: [task("R1", status)], page: { offset: 0, limit: 6, total: 2, hasMore: true } });
    if (status === "blocked") return jsonResponse(200, { ok: true, tasks: [task("R3", status)], page: { offset: 0, limit: 6, total: 1, hasMore: false } });
  }
  return jsonResponse(404, { ok: false, error: { code: "not_found" } });
}

function dashboardHwpodSpec() {
  return {
    ok: true,
    hwpodId: "hwpod-demo",
    name: "hwpod-demo",
    nodeId: "node-demo",
    authority: "test-registry",
    specPath: "/redacted/hwpod-spec.yaml",
    availability: { ok: true, status: "available", checkedAt: "2026-07-13T11:59:00.000Z" },
    document: { spec: {} }
  };
}

function dashboardHwpodRegistry() {
  return {
    describe() {
      return {
        mode: "hwpod-node-outbound-native-ws",
        pendingCount: 0,
        nodes: [{ nodeId: "node-demo", name: "Demo Node", status: "online", capabilities: ["node.health", "node.version", "node.inventory", "node.diagnostics"], inFlightCount: 0, maxInFlight: 1 }]
      };
    }
  };
}

function disabledKafkaBridge() {
  return { ready: Promise.resolve(), async stop() {}, describe() { return { status: "disabled" }; } };
}

function jsonResponse(status: number, body: unknown) {
  return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
}

async function listen(server: any) {
  await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
}

async function close(server: any) {
  await new Promise<void>((resolve, reject) => server.close((error: Error | null) => error ? reject(error) : resolve()));
}
