import { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

vi.mock("../../lib/i18n", () => ({
  t: (_key: string, fallback?: string) => fallback ?? _key,
}));

import LanguageSelector from "./LanguageSelector";

const roots: Root[] = [];

beforeEach(() => {
  window.localStorage.clear();
  window.history.replaceState({}, "", "/");
  document.body.innerHTML = "";
});

afterEach(() => {
  for (const root of roots.splice(0)) {
    act(() => {
      root.unmount();
    });
  }
  vi.restoreAllMocks();
});

function renderSelector() {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const root = createRoot(container);
  roots.push(root);

  act(() => {
    root.render(<LanguageSelector />);
  });

  return container;
}

describe("LanguageSelector", () => {
  it("prefers the locale stored in localStorage", () => {
    window.localStorage.setItem("locale", "en");

    const container = renderSelector();
    const select = container.querySelector("select") as HTMLSelectElement;

    expect(select.value).toBe("en");
  });

  it("falls back to the path locale when storage is empty", () => {
    window.history.replaceState({}, "", "/ko");

    const container = renderSelector();
    const select = container.querySelector("select") as HTMLSelectElement;

    expect(select.value).toBe("ko");
  });

  it("saves the selected locale and dispatches a development event", () => {
    vi.stubEnv("MODE", "development");
    const dispatchEvent = vi.spyOn(window, "dispatchEvent");
    window.history.replaceState({}, "", "/ko");

    const container = renderSelector();
    const select = container.querySelector("select") as HTMLSelectElement;

    act(() => {
      select.value = "en";
      select.dispatchEvent(new Event("change", { bubbles: true }));
    });

    expect(window.localStorage.getItem("locale")).toBe("en");
    expect(dispatchEvent).toHaveBeenCalled();
    expect(select.value).toBe("en");
  });
});
