import { describe, it, beforeEach, afterEach } from "node:test";
import assert from "node:assert";
import "../test-setup.ts";
import { createRoot, type Root } from "react-dom/client";
import { act } from "@testing-library/react";
import { CameraSelector } from "./CameraSelector.tsx";
import { useStore } from "../store/store.ts";

describe("CameraSelector", () => {
  let container: HTMLDivElement;
  let root: Root;

  beforeEach(() => {
    container = document.createElement("div");
    document.body.appendChild(container);
    root = createRoot(container);
    useStore.setState({
      models: [],
      selectedModelId: null,
      cameraView: "perspective",
      backdropUrl: null,
      availableModels: [],
    });
  });

  afterEach(() => {
    act(() => {
      root.unmount();
    });
    container.remove();
  });

  it("should render a dropdown", async () => {
    await act(async () => {
      root.render(<CameraSelector />);
    });

    const select = container.querySelector("select.camera-selector");
    assert.ok(select, "Should render a select dropdown");
  });

  it("should have perspective as default option", async () => {
    await act(async () => {
      root.render(<CameraSelector />);
    });

    const select = container.querySelector(
      "select.camera-selector",
    ) as HTMLSelectElement;
    assert.strictEqual(select?.value, "perspective");
  });

  it("should have all camera view options", async () => {
    await act(async () => {
      root.render(<CameraSelector />);
    });

    const options = container.querySelectorAll("select.camera-selector option");
    const values = Array.from(options).map(
      (opt) => (opt as HTMLOptionElement).value,
    );

    assert.ok(values.includes("perspective"), "Should have perspective option");
    assert.ok(values.includes("ortho-top"), "Should have ortho-top option");
    assert.ok(values.includes("ortho-front"), "Should have ortho-front option");
    assert.ok(values.includes("ortho-side"), "Should have ortho-side option");
  });

  it("should update store when selection changes", async () => {
    await act(async () => {
      root.render(<CameraSelector />);
    });

    const select = container.querySelector(
      "select.camera-selector",
    ) as HTMLSelectElement;

    await act(async () => {
      select.value = "ortho-top";
      select.dispatchEvent(new Event("change", { bubbles: true }));
    });

    assert.strictEqual(useStore.getState().cameraView, "ortho-top");
  });

  it("should be positioned as overlay", async () => {
    await act(async () => {
      root.render(<CameraSelector />);
    });

    const wrapper = container.querySelector(".camera-selector-wrapper");
    assert.ok(wrapper, "Should have wrapper for positioning");
  });

  it("should reflect store camera view state", async () => {
    useStore.setState({ cameraView: "ortho-front" });

    await act(async () => {
      root.render(<CameraSelector />);
    });

    const select = container.querySelector(
      "select.camera-selector",
    ) as HTMLSelectElement;
    assert.strictEqual(select?.value, "ortho-front");
  });
});
