/**
 * Unit tests for useTelegramTheme, getFallbackScheme, and applyTheme.
 * Ported from webapp/js/theme.test.js (getTheme, applyTheme).
 */

import { describe, it, expect, vi, afterEach } from "vitest";
import { renderHook } from "@testing-library/react";
import {
  useTelegramTheme,
  getFallbackScheme,
  applyTheme,
} from "./use-telegram-theme";

vi.mock("@telegram-apps/sdk-react", () => ({
  useSignal: vi.fn(() => undefined),
  isThemeParamsDark: vi.fn(),
  setMiniAppBackgroundColor: { isAvailable: vi.fn(() => false) },
  setMiniAppHeaderColor: { isAvailable: vi.fn(() => false) },
}));

describe("getFallbackScheme", () => {
  const originalMatchMedia = window.matchMedia;
  const originalGetComputedStyle = window.getComputedStyle;

  afterEach(() => {
    window.matchMedia = originalMatchMedia;
    window.getComputedStyle = originalGetComputedStyle;
    document.documentElement.removeAttribute("data-theme");
    vi.clearAllMocks();
  });

  it("returns dark when prefers-color-scheme is dark", () => {
    window.matchMedia = vi.fn((query: string) => ({
      matches: query === "(prefers-color-scheme: dark)",
      media: query,
      addEventListener: vi.fn(),
      removeEventListener: vi.fn(),
      addListener: vi.fn(),
      removeListener: vi.fn(),
      dispatchEvent: vi.fn(),
      onchange: null,
    })) as unknown as typeof window.matchMedia;
    expect(getFallbackScheme()).toBe("dark");
  });

  it("returns light when prefers-color-scheme is light", () => {
    window.matchMedia = vi.fn((query: string) => ({
      matches: query === "(prefers-color-scheme: light)",
      media: query,
      addEventListener: vi.fn(),
      removeEventListener: vi.fn(),
      addListener: vi.fn(),
      removeListener: vi.fn(),
      dispatchEvent: vi.fn(),
      onchange: null,
    })) as unknown as typeof window.matchMedia;
    expect(getFallbackScheme()).toBe("light");
  });

  it("uses --tg-color-scheme when set on document", () => {
    window.getComputedStyle = vi.fn(() =>
      Object.assign(
        {},
        {
          getPropertyValue: (prop: string) =>
            prop === "--tg-color-scheme" ? " light " : "",
        }
      )
    ) as unknown as typeof window.getComputedStyle;
    expect(getFallbackScheme()).toBe("light");
  });

  it("uses --tg-color-scheme dark when set", () => {
    window.getComputedStyle = vi.fn(() =>
      Object.assign(
        {},
        {
          getPropertyValue: (prop: string) =>
            prop === "--tg-color-scheme" ? "dark" : "",
        }
      )
    ) as unknown as typeof window.getComputedStyle;
    expect(getFallbackScheme()).toBe("dark");
  });
});

describe("applyTheme", () => {
  afterEach(() => {
    document.documentElement.removeAttribute("data-theme");
    vi.clearAllMocks();
  });

  it("sets data-theme to given scheme", () => {
    applyTheme("light");
    expect(document.documentElement.getAttribute("data-theme")).toBe("light");
    applyTheme("dark");
    expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
  });

  it("resolves scheme via getFallbackScheme when no argument", () => {
    window.matchMedia = vi.fn((query: string) => ({
      matches: query === "(prefers-color-scheme: dark)",
      media: query,
      addEventListener: vi.fn(),
      removeEventListener: vi.fn(),
      addListener: vi.fn(),
      removeListener: vi.fn(),
      dispatchEvent: vi.fn(),
      onchange: null,
    })) as unknown as typeof window.matchMedia;
    applyTheme();
    expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
  });
});

describe("useTelegramTheme", () => {
  const originalMatchMedia = window.matchMedia;
  const originalGetComputedStyle = window.getComputedStyle;

  afterEach(() => {
    window.matchMedia = originalMatchMedia;
    window.getComputedStyle = originalGetComputedStyle;
    document.documentElement.removeAttribute("data-theme");
    vi.clearAllMocks();
  });

  it("sets data-theme to dark when useSignal returns true", async () => {
    const { useSignal } = await import("@telegram-apps/sdk-react");
    vi.mocked(useSignal).mockReturnValue(true);
    renderHook(() => useTelegramTheme());
    expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
  });

  it("sets data-theme to light when useSignal returns false", async () => {
    const { useSignal } = await import("@telegram-apps/sdk-react");
    vi.mocked(useSignal).mockReturnValue(false);
    renderHook(() => useTelegramTheme());
    expect(document.documentElement.getAttribute("data-theme")).toBe("light");
  });
});
