import { describe, expect, test, vi } from "vitest";
import {
  DASHBOARD_SCHEMA_VERSION,
  type DashboardDocument,
} from "@dimensionlab/dashboard-model";
import { resolveDashboardDatasources } from ".";

describe("dashboard datasource resolution", () => {
  test("hydrates telemetry, service health, weather, and summary data from live adapters", async () => {
    const fetch = vi.fn(async (input: RequestInfo | URL) => {
      const url = String(input);

      if (url.startsWith("https://prometheus.example/api/v1/query_range")) {
        return jsonResponse({
          status: "success",
          data: {
            result: [
              {
                metric: { host: "linux-infra" },
                values: [
                  [1771430000, "10"],
                  [1771430060, "40"],
                  [1771430120, "30"],
                ],
              },
              {
                metric: { host: "linux-gpu" },
                values: [
                  [1771430000, "12"],
                  [1771430060, "24"],
                  [1771430120, "36"],
                ],
              },
            ],
          },
        });
      }

      if (url.startsWith("https://prometheus.example/api/v1/query")) {
        const query = new URL(url).searchParams.get("query") || "";
        if (query.includes("node_boot_time_seconds")) {
          return prometheusVector("90061");
        }
        if (query.includes("node_load15")) return prometheusVector("0.40");
        if (query.includes("node_load5")) return prometheusVector("0.46");
        if (query.includes("node_load1")) return prometheusVector("0.34");

        return jsonResponse({
          status: "success",
          data: {
            result: [
              {
                metric: { host: "linux-infra", mountpoint: "/home" },
                value: [1771430400, "88"],
              },
            ],
          },
        });
      }

      if (url.startsWith("https://api.open-meteo.com/v1/forecast")) {
        return jsonResponse({
          current: {
            apparent_temperature: 20.9,
            temperature_2m: 21.4,
            weather_code: 0,
            wind_speed_10m: 12,
          },
        });
      }

      if (url === "https://service.example/health") {
        return jsonResponse({
          status: "UP",
          ping: 42,
        });
      }

      throw new Error(`Unhandled test request: ${url}`);
    });

    const resolved = await resolveDashboardDatasources(testDashboard(), {
      fetch,
      prometheusBaseUrl: "https://prometheus.example",
    });

    expect(fetch).toHaveBeenCalledWith(
      expect.stringContaining("/api/v1/query?"),
      expect.objectContaining({ cache: "no-store" }),
    );
    expect(fetch).toHaveBeenCalledWith(
      expect.stringContaining("/api/v1/query_range?"),
      expect.objectContaining({ cache: "no-store" }),
    );

    const telemetry = resolved.telemetry[0];
    expect(telemetry.value).toEqual({ kind: "percent", value: 88 });
    expect(telemetry.severity).toBe("warning");
    expect(telemetry.detail).toBe("linux-infra /home");
    expect(telemetry.sparkline).toEqual([12, 40, 36]);

    const service = resolved.serviceGroups[0].services[0];
    expect(service.severity).toBe("ok");
    expect(service.detail).toBe("42 ms");

    const weather = resolved.modules?.find((module) => module.id === "weather-amsterdam");
    expect(weather?.value).toBe("21.4 C");
    expect(weather?.detail).toBe("Clear - feels 20.9 C - wind 12 km/h");
    expect(weather?.severity).toBe("ok");

    const summary = resolved.modules?.find((module) => module.id === "runtime-health-summary");
    expect(summary?.value).toBe("all systems operational");
    expect(summary?.detail).toBe("1 service ok");
    expect(summary?.severity).toBe("ok");

    expect(resolved.statusStrips[0].items).toEqual([
      { id: "system-status", label: "System Status", value: "All systems operational", severity: "ok" },
      { id: "last-sync", label: "Last Sync", value: "just now", severity: "ok" },
      { id: "uptime", label: "Uptime", value: "1d 1h 1m", severity: "ok" },
      { id: "load-avg", label: "Load Avg", value: "0.34 0.46 0.40", severity: "neutral" },
      { id: "auto-refresh", label: "Auto Refresh", value: "15s", severity: "neutral" },
    ]);

    expect(resolved).not.toBe(testDocument);
    expect(testDocument.telemetry[0].value.value).toBe(1);
  });
});

const testDocument = testDashboard();

function testDashboard(): DashboardDocument {
  return {
    schemaVersion: DASHBOARD_SCHEMA_VERSION,
    metadata: {
      title: "System Overview",
      refreshIntervalSeconds: 15,
    },
    layout: {
      telemetry: ["cpu"],
      serviceGroups: ["services"],
      statusStrips: ["footer"],
      modules: ["weather-amsterdam", "runtime-health-summary"],
    },
    telemetry: [
      {
        id: "cpu",
        label: "CPU",
        value: { kind: "percent", value: 1 },
        detail: "fallback",
        severity: "stale",
        thresholds: { warning: 70, danger: 90 },
        datasource: {
          type: "external",
          adapter: "prometheus",
          reference: "fixture_cpu_query",
        },
        sparkline: [1],
      },
    ],
    serviceGroups: [
      {
        id: "services",
        title: "Services",
        services: [
          {
            id: "api",
            label: "API",
            description: "Example API",
            severity: "stale",
            detail: "fallback",
            datasource: {
              type: "external",
              adapter: "http-status",
              reference: "GET https://service.example/health",
            },
          },
        ],
      },
    ],
    statusStrips: [
      {
        id: "footer",
        items: [
          { id: "system-status", label: "System Status", value: "fallback", severity: "ok" },
          { id: "last-sync", label: "Last Sync", value: "fallback", severity: "stale" },
          { id: "uptime", label: "Uptime", value: "fallback", severity: "ok" },
          { id: "load-avg", label: "Load Avg", value: "fallback", severity: "neutral" },
          { id: "auto-refresh", label: "Auto Refresh", value: "fallback", severity: "neutral" },
        ],
      },
    ],
    modules: [
      {
        id: "weather-amsterdam",
        kind: "weather",
        title: "Amsterdam",
        value: "fallback",
        detail: "fallback",
        severity: "stale",
        datasource: {
          type: "external",
          adapter: "weather",
          reference: "open-meteo:latitude=52.3676&longitude=4.9041",
        },
      },
      {
        id: "runtime-health-summary",
        kind: "summary",
        title: "Runtime Health",
        value: "fallback",
        detail: "fallback",
        severity: "stale",
        datasource: {
          type: "placeholder",
          reason: "summary pending live health aggregation",
        },
      },
    ],
  };
}

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

function prometheusVector(value: string): Response {
  return jsonResponse({
    status: "success",
    data: {
      result: [
        {
          metric: { host: "linux-infra" },
          value: [1771430400, value],
        },
      ],
    },
  });
}
