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 { Sidebar } from "./Sidebar.tsx";
import { useStore } from "../store/store.ts";

describe("Sidebar", () => {
  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: [
        { id: "servbot", name: "Servbot", url: "/models/servbot.gltf" },
        { id: "megaman", name: "Megaman", url: "/models/megaman_volnutt.gltf" },
        { id: "tron", name: "Tron Bonne", url: "/models/tron_bonne.gltf" },
      ],
    });
  });

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

  it("should render available models list", async () => {
    await act(async () => {
      root.render(<Sidebar />);
    });

    const sidebar = container.querySelector(".sidebar");
    assert.ok(sidebar, "Sidebar should be rendered");

    const modelItems = container.querySelectorAll(".model-item");
    assert.strictEqual(modelItems.length, 3, "Should render 3 model items");
  });

  it("should display model names", async () => {
    await act(async () => {
      root.render(<Sidebar />);
    });

    const modelNames = container.querySelectorAll(".model-name");
    const names = Array.from(modelNames).map((item) => item.textContent);

    assert.ok(names.includes("Servbot"), "Should display Servbot");
    assert.ok(names.includes("Megaman"), "Should display Megaman");
    assert.ok(names.includes("Tron Bonne"), "Should display Tron Bonne");
  });

  it("should have Add buttons for each model", async () => {
    await act(async () => {
      root.render(<Sidebar />);
    });

    const addButtons = container.querySelectorAll(".add-model-btn");
    assert.strictEqual(addButtons.length, 3, "Should have 3 Add buttons");

    addButtons.forEach((btn) => {
      assert.strictEqual(btn.textContent, "Add", 'Button should say "Add"');
    });
  });

  it("should add model to scene when Add button is clicked", async () => {
    await act(async () => {
      root.render(<Sidebar />);
    });

    const addButtons = container.querySelectorAll(".add-model-btn");
    const firstAddButton = addButtons[0] as HTMLButtonElement;

    await act(async () => {
      firstAddButton.click();
    });

    const models = useStore.getState().models;
    assert.strictEqual(models.length, 1, "Should have 1 model in scene");
    assert.strictEqual(models[0].sourceId, "servbot", "Should be a servbot");
  });

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

    const title = container.querySelector(".sidebar-title");
    assert.ok(title, "Should have a title");
    assert.ok(
      title?.textContent?.includes("Models"),
      'Title should contain "Models"',
    );
  });
});
