import { expect, test } from "@playwright/test";

import { createBoxBrush } from "../../src/document/brushes";
import { createEmptySceneDocument } from "../../src/document/scene-document";
import {
  clickViewportAtRatio,
  getEditorStoreSnapshot,
  replaceSceneDocument
} from "./viewport-test-helpers";

test("whitebox component selection modes keep object picking intentional across perspective and orthographic panes", async ({ page }) => {
  const pageErrors: string[] = [];
  const consoleErrors: string[] = [];

  page.on("pageerror", (error) => {
    pageErrors.push(error.message);
  });

  page.on("console", (message) => {
    if (message.type() === "error") {
      consoleErrors.push(message.text());
    }
  });

  await page.goto("/");
  await page.evaluate((storageKey) => {
    window.localStorage.removeItem(storageKey);
  }, "webeditor3d.scene-document-draft");
  await page.reload();

  test.skip((await page.getByText("Viewport Unavailable").count()) > 0, "WebGL is unavailable in this Playwright environment.");

  const brush = createBoxBrush({
    id: "brush-selection-modes-main",
    name: "Selection Fixture",
    center: {
      x: 0,
      y: 1,
      z: 0
    },
    size: {
      x: 2,
      y: 2,
      z: 2
    }
  });

  await replaceSceneDocument(page, {
    ...createEmptySceneDocument({ name: "Selection Modes Scene" }),
    brushes: {
      [brush.id]: brush
    }
  });

  await page.evaluate(({ target }) => {
    const store = (window as Window & {
      __webeditor3dEditorStore?: {
        getState(): {
          viewportPanels: {
            topLeft: {
              cameraState: {
                target: { x: number; y: number; z: number };
                perspectiveOrbit: { radius: number; theta: number; phi: number };
                orthographicZoom: number;
              };
            };
          };
        };
        setViewportPanelCameraState(panelId: "topLeft", cameraState: {
          target: { x: number; y: number; z: number };
          perspectiveOrbit: { radius: number; theta: number; phi: number };
          orthographicZoom: number;
        }): void;
      };
    }).__webeditor3dEditorStore;

    if (store === undefined) {
      throw new Error("Editor store debug hook is unavailable.");
    }

    const topLeftCameraState = store.getState().viewportPanels.topLeft.cameraState;

    store.setViewportPanelCameraState("topLeft", {
      ...topLeftCameraState,
      target,
      perspectiveOrbit: {
        radius: 4.5,
        theta: 0.72,
        phi: 1.08
      }
    });
  }, { target: brush.center });

  await expect(page.getByTestId("whitebox-selection-mode-object")).toHaveAttribute("aria-pressed", "true");
  await clickViewportAtRatio(page, "topLeft", 0.5, 0.52);
  let snapshot = await getEditorStoreSnapshot(page);
  expect(snapshot.whiteboxSelectionMode).toBe("object");
  expect(snapshot.selection).toMatchObject({
    kind: "brushes",
    ids: [brush.id]
  });

  await page.getByTestId("viewport-layout-quad").click();

  await page.evaluate(({ target }) => {
    const store = (window as Window & {
      __webeditor3dEditorStore?: {
        getState(): {
          viewportPanels: {
            topRight: {
              cameraState: {
                target: { x: number; y: number; z: number };
                perspectiveOrbit: { radius: number; theta: number; phi: number };
                orthographicZoom: number;
              };
            };
          };
        };
        setViewportPanelViewMode(panelId: "topRight", viewMode: "top"): void;
        setViewportPanelCameraState(panelId: "topRight", cameraState: {
          target: { x: number; y: number; z: number };
          perspectiveOrbit: { radius: number; theta: number; phi: number };
          orthographicZoom: number;
        }): void;
      };
    }).__webeditor3dEditorStore;

    if (store === undefined) {
      throw new Error("Editor store debug hook is unavailable.");
    }

    const topRightCameraState = store.getState().viewportPanels.topRight.cameraState;
    store.setViewportPanelViewMode("topRight", "top");
    store.setViewportPanelCameraState("topRight", {
      ...topRightCameraState,
      target,
      orthographicZoom: 8
    });
  }, { target: brush.center });

  await page.getByTestId("whitebox-selection-mode-face").click();
  await expect(page.getByTestId("whitebox-selection-mode-face")).toHaveAttribute("aria-pressed", "true");
  await clickViewportAtRatio(page, "topRight", 0.5, 0.5);
  snapshot = await getEditorStoreSnapshot(page);
  expect(snapshot.whiteboxSelectionMode).toBe("face");
  expect(snapshot.selection).toMatchObject({
    kind: "brushFace",
    brushId: brush.id,
    faceId: "posY"
  });

  await page.getByTestId("whitebox-selection-mode-edge").click();
  await expect(page.getByTestId("whitebox-selection-mode-edge")).toHaveAttribute("aria-pressed", "true");
  await clickViewportAtRatio(page, "topRight", 0.5, 0.12);
  snapshot = await getEditorStoreSnapshot(page);
  expect(snapshot.whiteboxSelectionMode).toBe("edge");
  expect(snapshot.selection).toMatchObject({
    kind: "brushEdge",
    brushId: brush.id,
    edgeId: "edgeX_posY_negZ"
  });

  await page.getByTestId("whitebox-selection-mode-vertex").click();
  await expect(page.getByTestId("whitebox-selection-mode-vertex")).toHaveAttribute("aria-pressed", "true");
  await clickViewportAtRatio(page, "topRight", 0.88, 0.12);
  snapshot = await getEditorStoreSnapshot(page);
  expect(snapshot.whiteboxSelectionMode).toBe("vertex");
  expect(snapshot.selection).toMatchObject({
    kind: "brushVertex",
    brushId: brush.id,
    vertexId: "posX_posY_negZ"
  });

  await page.getByTestId("whitebox-selection-mode-object").click();
  await clickViewportAtRatio(page, "topRight", 0.5, 0.5);
  snapshot = await getEditorStoreSnapshot(page);
  expect(snapshot.whiteboxSelectionMode).toBe("object");
  expect(snapshot.selection).toMatchObject({
    kind: "brushes",
    ids: [brush.id]
  });

  expect(pageErrors).toEqual([]);
  expect(consoleErrors).toEqual([]);
});
