/**
 * @vitest-environment jsdom
 */

import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { useIsMobileViewport } from "./useIsMobileViewport.js";

describe("useIsMobileViewport", () => {
  let matchMediaMock: ReturnType<typeof vi.fn>;
  let listeners: ((e: { matches: boolean }) => void)[];
  let currentMatches = false;

  beforeEach(() => {
    listeners = [];
    currentMatches = false;
    matchMediaMock = vi.fn().mockImplementation((query: string) => ({
      matches: currentMatches,
      media: query,
      addEventListener: (_type: string, listener: (e: { matches: boolean }) => void) => {
        listeners.push(listener);
      },
      removeEventListener: () => {},
      dispatchEvent: () => false,
    }));
    Object.defineProperty(window, "matchMedia", { value: matchMediaMock, configurable: true });
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("returns false when viewport is wider than mobile breakpoint", () => {
    currentMatches = false;
    const { result } = renderHook(() => useIsMobileViewport());
    expect(result.current).toBe(false);
  });

  it("returns true when viewport is narrower than mobile breakpoint", () => {
    currentMatches = true;
    const { result } = renderHook(() => useIsMobileViewport());
    expect(result.current).toBe(true);
  });

  it("updates when media-query match changes", () => {
    currentMatches = false;
    const { result } = renderHook(() => useIsMobileViewport());
    expect(result.current).toBe(false);
    act(() => {
      for (const l of listeners) l({ matches: true });
    });
    expect(result.current).toBe(true);
  });
});
