import { afterEach, expect, test, vi } from "vitest";
import { applyTheme, readTheme, resolveTheme, THEME_KEY } from "./theme";

function mockMatchMedia(matches: boolean) {
  vi.stubGlobal("matchMedia", (query: string) => ({
    matches,
    media: query,
    onchange: null,
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    addListener: vi.fn(),
    removeListener: vi.fn(),
    dispatchEvent: vi.fn(),
  }));
}

afterEach(() => {
  vi.unstubAllGlobals();
  localStorage.clear();
  document.documentElement.classList.remove("dark");
});

test("resolveTheme returns explicit values verbatim", () => {
  expect(resolveTheme("light")).toBe("light");
  expect(resolveTheme("dark")).toBe("dark");
});

test("resolveTheme maps system via prefers-color-scheme", () => {
  mockMatchMedia(true);
  expect(resolveTheme("system")).toBe("dark");
  mockMatchMedia(false);
  expect(resolveTheme("system")).toBe("light");
});

test("readTheme defaults to system when unset or invalid", () => {
  expect(readTheme()).toBe("system");
  localStorage.setItem(THEME_KEY, "bogus");
  expect(readTheme()).toBe("system");
  localStorage.setItem(THEME_KEY, "dark");
  expect(readTheme()).toBe("dark");
});

test("applyTheme syncs the theme-color meta when present", () => {
  const meta = document.createElement("meta");
  meta.setAttribute("name", "theme-color");
  document.head.appendChild(meta);
  try {
    mockMatchMedia(false);
    applyTheme("dark");
    expect(meta.getAttribute("content")).toBe("#0a0a0a");
    applyTheme("light");
    expect(meta.getAttribute("content")).toBe("#ffffff");
  } finally {
    meta.remove();
  }
});

test("applyTheme toggles the dark class on documentElement", () => {
  mockMatchMedia(false);
  applyTheme("dark");
  expect(document.documentElement.classList.contains("dark")).toBe(true);
  applyTheme("light");
  expect(document.documentElement.classList.contains("dark")).toBe(false);
  mockMatchMedia(true);
  applyTheme("system");
  expect(document.documentElement.classList.contains("dark")).toBe(true);
});
