import { cleanup, screen } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";

import {
  createBackgroundSchema,
  createIntrinsicMediaSchema,
  createSchema,
  createUploadDefaultSchema,
  renderCanvasShell,
} from "./canvas-shell-test-utils";
import { useToolcraftProductSceneFrame } from "./product-scene-surface";

afterEach(() => {
  cleanup();
});

describe("CanvasShell rendering", () => {
  it("uses product bounds as the live infinite preview frame", () => {
    function ProductFrameProbe(): React.JSX.Element {
      const frame = useToolcraftProductSceneFrame();
      return <output data-testid="product-frame">{JSON.stringify(frame)}</output>;
    }

    const { container } = renderCanvasShell({
      children: <ProductFrameProbe />,
      initialState: {
        canvas: {
          mode: "infinite",
          offset: { x: 0, y: 0 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 100,
        },
      },
      productSceneBoundsProvider: () => [
        { height: 260, width: 420, x: -210, y: -130 },
      ],
    });
    const productScene = container.querySelector<HTMLElement>(
      "[data-toolcraft-product-scene]",
    );

    expect(productScene?.style.height).toBe("260px");
    expect(productScene?.style.left).toBe("-210px");
    expect(productScene?.style.top).toBe("-130px");
    expect(productScene?.style.width).toBe("420px");
    expect(screen.getByTestId("product-frame").textContent).toBe(
      JSON.stringify({
        kind: "infinite",
        rect: { height: 260, width: 420, x: -210, y: -130 },
      }),
    );
  });

  it("renders the editable canvas at the schema size", () => {
    const { container } = renderCanvasShell();

    const editableCanvas = container.querySelector<HTMLElement>(
      "[data-toolcraft-editable-canvas]",
    );

    expect(editableCanvas?.style.width).toBe("300px");
    expect(editableCanvas?.style.height).toBe("200px");
  });

  it("renders infinite mode without an editable-artboard boundary", () => {
    const { container } = renderCanvasShell({
      children: <div data-testid="infinite-content" />,
      initialState: {
        canvas: {
          mode: "infinite",
          offset: { x: 0, y: 0 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 100,
        },
      },
    });

    const scene = container.querySelector<HTMLElement>(
      "[data-toolcraft-infinite-scene]",
    );
    const slot = container.querySelector<HTMLElement>(
      "[data-toolcraft-canvas-slot]",
    );

    expect(scene).toBeTruthy();
    expect(scene?.style.width).toBe("");
    expect(scene?.style.height).toBe("");
    expect(scene?.className).toContain("overflow-visible");
    expect(slot?.className).toContain("contents");
    expect(
      container.querySelector("[data-toolcraft-editable-canvas]"),
    ).toBeNull();
    expect(
      container.querySelector<HTMLElement>("[data-slot='toolcraft-runtime-canvas']")
        ?.style.backgroundColor,
    ).toBe("");
  });

  it("mounts product viewport content only in Infinity behind the transformed world", () => {
    const finite = renderCanvasShell({
      infiniteCanvasContent: <div data-testid="infinite-viewport-content" />,
    });

    expect(
      finite.container.querySelector("[data-toolcraft-infinite-canvas-content]"),
    ).toBeNull();
    finite.unmount();

    const { container } = renderCanvasShell({
      children: <div data-testid="bounded-product-content" />,
      infiniteCanvasContent: <div data-testid="infinite-viewport-content" />,
      initialState: {
        canvas: {
          mode: "infinite",
          offset: { x: 42, y: -18 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 75,
        },
      },
    });
    const backdrop = container.querySelector<HTMLElement>(
      "[data-toolcraft-infinite-canvas-content]",
    );
    const world = container.querySelector<HTMLElement>(
      "[data-toolcraft-canvas-world]",
    );

    expect(backdrop).toBeTruthy();
    expect(backdrop?.className).toContain("pointer-events-none");
    expect(backdrop?.className).toContain("absolute");
    expect(backdrop?.className).toContain("inset-0");
    expect(backdrop?.style.transform).toBe("");
    expect(backdrop?.nextElementSibling).toBe(world);
    expect(screen.getByTestId("infinite-viewport-content")).toBeTruthy();
    expect(screen.getByTestId("bounded-product-content")).toBeTruthy();
  });

  it("fills the complete infinite viewport with the selected Background color", () => {
    const { container } = renderCanvasShell({
      initialState: {
        canvas: {
          mode: "infinite",
          offset: { x: 0, y: 0 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 100,
        },
        values: {
          "appearance.background": "#D4CECA",
          "export.includeBackground": true,
        },
      },
      schema: createBackgroundSchema(),
    });

    const viewport = container.querySelector<HTMLElement>(
      "[data-slot='toolcraft-runtime-canvas']",
    );

    expect(viewport?.dataset.toolcraftInfiniteBackgroundColor).toBe("#D4CECA");
    expect(viewport?.style.backgroundColor).toBe("rgb(212, 206, 202)");
    expect(
      container.querySelector("[data-toolcraft-editable-canvas]"),
    ).toBeNull();
  });

  it("normalizes structured color ingress before filling the infinite viewport", () => {
    const { container } = renderCanvasShell({
      initialState: {
        canvas: {
          mode: "infinite",
          offset: { x: 0, y: 0 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 100,
        },
        values: {
          "appearance.background": { hex: "#CB9672" },
          "export.includeBackground": true,
        },
      },
      schema: createBackgroundSchema(),
    });

    const viewport = container.querySelector<HTMLElement>(
      "[data-slot='toolcraft-runtime-canvas']",
    );

    expect(viewport?.dataset.toolcraftInfiniteBackgroundColor).toBe("#CB9672");
    expect(viewport?.style.backgroundColor).toBe("rgb(203, 150, 114)");
  });

  it("does not render a fixed editable canvas for explicit intrinsic media sizing", () => {
    const { container } = renderCanvasShell({
      schema: createIntrinsicMediaSchema(),
    });

    expect(container.querySelector("[data-toolcraft-editable-canvas]")).toBeNull();
  });

  it("renders the canvas slot inside the editable canvas when custom app content is provided", () => {
    const { container } = renderCanvasShell({
      children: <div data-testid="custom-canvas-renderer" />,
      schema: createUploadDefaultSchema(),
    });

    const editableCanvas = container.querySelector<HTMLElement>(
      "[data-toolcraft-editable-canvas]",
    );
    const slot = container.querySelector<HTMLElement>(
      "[data-toolcraft-canvas-slot]",
    );

    expect(editableCanvas).toBeTruthy();
    expect(slot?.parentElement).toBe(editableCanvas);
    expect(screen.getByTestId("custom-canvas-renderer")).toBeTruthy();
  });

  it("does not render decorative canvas background dots", () => {
    const { container } = renderCanvasShell();

    const pattern = container.querySelector<HTMLElement>("[data-toolcraft-canvas-grid]");
    const world = container.querySelector<HTMLElement>("[data-toolcraft-canvas-world]");

    expect(world).toBeTruthy();
    expect(pattern).toBeNull();
  });

  it("moves and scales the canvas world without decorative background dots", () => {
    const { container } = renderCanvasShell({
      initialState: {
        canvas: {
          offset: { x: 12, y: -8 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 150,
        },
      },
      schema: createSchema(),
    });

    const pattern = container.querySelector<HTMLElement>("[data-toolcraft-canvas-grid]");
    const world = container.querySelector<HTMLElement>("[data-toolcraft-canvas-world]");

    expect(pattern).toBeNull();
    expect(world?.style.transform).toBe("translate(-50%, -50%) translate(12px, -8px) scale(1.5)");
  });

  it("keeps minimum zoom world transform without decorative background dots", () => {
    const { container } = renderCanvasShell({
      initialState: {
        canvas: {
          offset: { x: 3200, y: -2400 },
          size: { height: 200, unit: "px", width: 300 },
          zoom: 25,
        },
      },
      schema: createSchema(),
    });

    const pattern = container.querySelector<HTMLElement>("[data-toolcraft-canvas-grid]");
    const world = container.querySelector<HTMLElement>("[data-toolcraft-canvas-world]");

    expect(pattern).toBeNull();
    expect(world?.style.transform).toBe(
      "translate(-50%, -50%) translate(3200px, -2400px) scale(0.25)",
    );
  });
});
