// AttentionList: ranking semantics of attentionRows — pricing-missing
// pinned first, top-5 savings, top-3 WoW increases, one row per region,
// cap at 8 — plus render smoke. Fabricated RegionOverviewRow fixtures.

import { describe, expect, it, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { AttentionList, attentionRows } from "@/components/dashboard/AttentionList";
import { mkOverviewRow } from "../helpers/mk-overview-row";

// next/link requires app-router context; render it as a plain anchor.
vi.mock("next/link", () => ({
  default: ({ href, children }: { href: string; children: React.ReactNode }) => (
    <a href={href}>{children}</a>
  ),
}));


describe("attentionRows", () => {
  it("pins pricing-missing regions first, priciest first", () => {
    const rows = attentionRows([
      mkOverviewRow("rich-savings", { potentialMonthlySavingsUsd: 900 }),
      mkOverviewRow("gap-2", { pricingMissing: true, monthlyCostUsd: 100 }),
      mkOverviewRow("gap-1", { pricingMissing: true, monthlyCostUsd: 500 }),
    ]);
    expect(rows.map((r) => r.region.regionKey)).toEqual(["gap-1", "gap-2", "rich-savings"]);
    expect(rows[0].primary).toBe("pricing");
  });

  it("keeps only the top-5 savings and top-3 WoW entries", () => {
    const regions = Array.from({ length: 7 }, (_, i) =>
      mkOverviewRow(`s-${i}`, { potentialMonthlySavingsUsd: 100 - i }),
    ).concat(
      Array.from({ length: 4 }, (_, i) => mkOverviewRow(`w-${i}`, { deltaMonthlyCostUsd: 50 - i })),
    );
    const rows = attentionRows(regions);
    expect(rows.filter((r) => r.region.regionKey.startsWith("s-")).length).toBe(5);
    expect(rows.filter((r) => r.region.regionKey.startsWith("w-")).length).toBe(3);
    expect(rows.map((r) => r.region.regionKey)).toEqual([
      "s-0", "s-1", "s-2", "s-3", "s-4", "w-0", "w-1", "w-2",
    ]);
  });

  it("dedupes: a region appears once under its highest-priority signal", () => {
    const rows = attentionRows([
      mkOverviewRow("both", { pricingMissing: true, potentialMonthlySavingsUsd: 500, deltaMonthlyCostUsd: 50 }),
      mkOverviewRow("saver", { potentialMonthlySavingsUsd: 100 }),
    ]);
    const both = rows.filter((r) => r.region.regionKey === "both");
    expect(both.length).toBe(1);
    expect(both[0].primary).toBe("pricing");
    expect(both[0].badges.length).toBeGreaterThanOrEqual(2);
  });

  it("caps the list at 8 rows", () => {
    // 3 pricing + 5 savings + 3 WoW = 11 candidates; the cap keeps 8.
    const regions = Array.from({ length: 3 }, (_, i) =>
      mkOverviewRow(`p-${i}`, { pricingMissing: true, monthlyCostUsd: 300 - i }),
    ).concat(
      Array.from({ length: 5 }, (_, i) => mkOverviewRow(`s-${i}`, { potentialMonthlySavingsUsd: 100 - i })),
      Array.from({ length: 3 }, (_, i) => mkOverviewRow(`w-${i}`, { deltaMonthlyCostUsd: 50 - i })),
    );
    const rows = attentionRows(regions);
    expect(rows.length).toBe(8);
    // pricing candidates survive the cap; the WoW tail drops off.
    expect(rows.filter((r) => r.region.regionKey.startsWith("w-")).length).toBe(0);
  });

  it("negative WoW movement and zero savings never rank", () => {
    expect(
      attentionRows([
        mkOverviewRow("calm", { deltaMonthlyCostUsd: -50, potentialMonthlySavingsUsd: 0 }),
      ]),
    ).toEqual([]);
  });
});

describe("AttentionList", () => {
  it("renders region links and signal badges", () => {
    render(
      <AttentionList
        regions={[
          mkOverviewRow("aws-us-west-2", {
            pricingMissing: true,
            pricingMissingTypes: ["m6i.xlarge"],
            idleCount: 2,
            overprovisionedCount: 3,
          }),
        ]}
      />,
    );
    expect(screen.getByText("aws-us-west-2").closest("a")?.getAttribute("href")).toBe(
      "/insight/aws-us-west-2",
    );
    expect(screen.getByText("pricing missing")).toBeTruthy();
    expect(screen.getByText("2 idle")).toBeTruthy();
    expect(screen.getByText("3 overprovisioned")).toBeTruthy();
  });

  it("shows the healthy empty state", () => {
    render(<AttentionList regions={[mkOverviewRow("calm")]} />);
    expect(screen.getByText(/Nothing flagged/)).toBeTruthy();
  });
});
