import { describe, expect, it } from "@jest/globals";
import { RouterLinkStub, shallowMount } from "@vue/test-utils";

import MetricRow from "../../../frontend/src/components/MetricRow.vue";
import ServiceGrid from "../../../frontend/src/components/ServiceGrid.vue";
import StatsGrid from "../../../frontend/src/components/StatsGrid.vue";
import { fallbackHardware } from "../../../frontend/src/data/sample.js";

describe("shared dashboard components", () => {
  it("renders metric cards", () => {
    const wrapper = shallowMount(MetricRow, {
      props: {
        items: [
          { label: "Nodes", value: "26", note: "atlas platform" },
          { label: "Storage", value: "80 TB", note: "Longhorn" },
        ],
      },
    });

    expect(wrapper.text()).toContain("Nodes");
    expect(wrapper.text()).toContain("26");
    expect(wrapper.text()).toContain("Longhorn");
  });

  it("summarizes node state in the stats grid", () => {
    const wrapper = shallowMount(StatsGrid, {
      props: { hardware: fallbackHardware() },
    });

    expect(wrapper.text()).toContain("Control plane");
    expect(wrapper.text()).toContain("3");
    expect(wrapper.text()).toContain("offline");
    expect(wrapper.text()).toContain("titan-16");
  });

  it("hides the attention card when every worker is healthy", () => {
    const wrapper = shallowMount(StatsGrid, {
      props: {
        hardware: {
          clusters: [
            {
              name: "atlas",
              nodes: [{ name: "titan-0a", role: "control-plane", status: "ready" }],
            },
          ],
          specialty: [],
        },
      },
    });

    expect(wrapper.text()).not.toContain("Attention");
  });

  it("distinguishes internal and external service links", () => {
    const wrapper = shallowMount(ServiceGrid, {
      global: {
        stubs: {
          RouterLink: RouterLinkStub,
        },
      },
      props: {
        services: [
          { name: "Atlas AI", category: "ai", summary: "Chat", link: "/ai/chat", icon: "🤖" },
          { name: "Nextcloud", category: "productivity", summary: "Files", link: "https://cloud.example.dev", icon: "☁️" },
          { name: "Bad Link", category: "broken", summary: "invalid", link: "not a url", icon: "❓" },
        ],
      },
    });

    expect(wrapper.text()).toContain("Atlas AI");
    expect(wrapper.text()).toContain("cloud.example.dev");
    expect(wrapper.text()).toContain("not a url");
    expect(wrapper.findComponent(RouterLinkStub).exists()).toBe(true);
  });

  it("falls back to default service rendering when data is sparse", () => {
    const wrapper = shallowMount(ServiceGrid, {
      global: {
        stubs: {
          RouterLink: RouterLinkStub,
        },
      },
      props: {
        services: [
          { name: "Muted Service", category: "dev", summary: "planned", link: "", status: "planned" },
          { name: "Plain Service", category: "dev", summary: "fallback icon", link: "/apps" },
        ],
      },
    });

    expect(wrapper.text()).toContain("Muted Service");
    expect(wrapper.text()).toContain("fallback icon");
    expect(wrapper.findAll(".service").length).toBe(2);
    expect(wrapper.findComponent(RouterLinkStub).exists()).toBe(true);
  });

  it("renders empty and partial hardware states safely", () => {
    const wrapper = shallowMount(StatsGrid, {
      props: {
        hardware: {
          clusters: [{ name: "atlas", nodes: [{ name: "solo", role: "worker", status: "ready" }] }],
          specialty: [{ name: "standalone", role: "Spare node", status: "ready" }],
        },
      },
    });

    expect(wrapper.text()).toContain("1 nodes total");
    expect(wrapper.text()).toContain("0");
    expect(wrapper.text()).toContain("standalone");
  });

  it("falls back cleanly when no hardware prop is provided", () => {
    const wrapper = shallowMount(StatsGrid, {
      props: {},
    });

    expect(wrapper.text()).toContain("0 nodes total");
    expect(wrapper.text()).not.toContain("Attention");
  });
});
