import { describe, expect, it } from "vitest";
import {
  defineToolcraft,
  fireEvent,
  renderControlsPanelWithSchema,
  screen,
  waitFor,
} from "../testing/controls-panel-test-utils";

describe("ControlsPanel collection actions", () => {
  it("renders collection actions as add/remove controls for runtime item arrays", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                colors: {
                  defaultValue: [{ hex: "#DFFF1A" }, { hex: "#8CFF3A" }],
                  itemControl: {
                    defaultValue: { hex: "#C1FF00" },
                    label: "Color",
                    type: "color",
                  },
                  label: "Colors",
                  minItems: 1,
                  recommendedMaxItems: 2,
                  target: "bead.colors",
                  type: "collectionActions",
                },
              },
              title: "Bead Colors",
            },
          ],
          title: "Controls",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);

    const addButton = screen.getByRole("button", { name: "Add Color" });
    const removeButton = screen.getByRole("button", { name: "Remove Color" });
    const collectionHeader = container.querySelector(
      '[data-slot="collection-actions-control-header"]',
    );
    const colorGrid = container.querySelector(
      '[data-slot="collection-actions-items-grid"]',
    );

    expect(collectionHeader?.textContent).toContain("Colors");
    expect(collectionHeader?.lastElementChild?.contains(removeButton)).toBe(true);
    expect(collectionHeader?.lastElementChild?.contains(addButton)).toBe(true);
    expect(colorGrid).toBeTruthy();
    expect(colorGrid?.children).toHaveLength(2);
    expect(
      container.querySelector('[data-slot="collection-item-groups"]'),
    ).toBeNull();
    expect(screen.queryByText("Color 1")).toBeNull();
    expect(screen.queryByText("Color 2")).toBeNull();

    fireEvent.click(addButton);
    fireEvent.click(addButton);

    let values = JSON.parse(screen.getByTestId("values-json").textContent ?? "{}");

    expect(values["bead.colors"]).toHaveLength(4);
    expect(screen.queryByText("Color 4")).toBeNull();
    expect(colorGrid?.children).toHaveLength(4);
    expect((addButton as HTMLButtonElement).disabled).toBe(false);

    fireEvent.click(removeButton);
    fireEvent.click(removeButton);
    fireEvent.click(removeButton);

    values = JSON.parse(screen.getByTestId("values-json").textContent ?? "{}");

    expect(values["bead.colors"]).toHaveLength(1);
    expect((removeButton as HTMLButtonElement).disabled).toBe(true);
  });

  it("adds, edits, separates, and removes complete logical item records", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                layers: {
                  defaultValue: [
                    {
                      invert: true,
                      rendererToken: "keep",
                      strength: 0.4,
                    },
                  ],
                  itemControls: {
                    strength: {
                      defaultValue: 0.5,
                      label: "Strength",
                      max: 1,
                      min: 0,
                      step: 0.1,
                      type: "slider",
                    },
                    invert: {
                      defaultValue: false,
                      label: "Invert",
                      type: "switch",
                    },
                  },
                  itemLabel: "Layer",
                  minItems: 1,
                  target: "surface.layers",
                  type: "collectionActions",
                },
              },
              title: "Surface Layers",
            },
          ],
          title: "Controls",
        },
      },
    });
    const { container } = renderControlsPanelWithSchema(schema);

    expect(
      container.querySelectorAll('[data-slot="collection-item-group"]'),
    ).toHaveLength(1);
    expect(screen.queryByText(/Item 1/u)).toBeNull();

    fireEvent.click(screen.getByRole("button", { name: "Add Layer" }));
    let values = JSON.parse(
      screen.getByTestId("values-json").textContent ?? "{}",
    );
    expect(values["surface.layers"]).toEqual([
      { invert: true, rendererToken: "keep", strength: 0.4 },
      { invert: false, strength: 0.5 },
    ]);

    const groups = container.querySelectorAll(
      '[data-slot="collection-item-group"]',
    );
    expect(groups).toHaveLength(2);
    expect(groups[0]?.className).not.toContain("border-t");
    expect(groups[1]?.className).toContain("border-t");

    fireEvent.click(
      screen.getAllByRole("button", { name: "Edit Strength value" })[0]!,
    );
    const editor = screen.getByRole("textbox", { name: "Strength value" });
    editor.textContent = "0.7";
    fireEvent.keyDown(editor, { key: "Enter" });
    values = JSON.parse(screen.getByTestId("values-json").textContent ?? "{}");
    expect(values["surface.layers"][0]).toEqual({
      invert: true,
      rendererToken: "keep",
      strength: 0.7,
    });

    fireEvent.click(screen.getByRole("button", { name: "Remove Layer" }));
    expect(
      container.querySelectorAll('[data-slot="collection-item-group"]'),
    ).toHaveLength(1);
  });

  it("renders collection item controls beyond color lists", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                labels: {
                  defaultValue: ["Alpha"],
                  itemControl: {
                    defaultValue: "New label",
                    label: "Label",
                    type: "text",
                  },
                  minItems: 1,
                  target: "glyph.labels",
                  type: "collectionActions",
                },
              },
              title: "Glyph Labels",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    fireEvent.click(screen.getByRole("button", { name: "Add Label" }));

    const values = JSON.parse(screen.getByTestId("values-json").textContent ?? "{}");

    expect(values["glyph.labels"]).toEqual(["Alpha", "New label"]);
    expect(screen.getByDisplayValue("Alpha")).toBeTruthy();
    expect(screen.getByDisplayValue("New label")).toBeTruthy();
  });

  it("keeps a collection font picker color popover open while editing its color surface", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                textStyles: {
                  defaultValue: [
                    {
                      color: "#FFFFFF",
                      fontId: "inter",
                      fontSize: 16,
                      fontWeight: "400",
                      letterSpacing: "normal",
                      lineHeight: "normal",
                      opacity: 100,
                      textCase: "original",
                    },
                  ],
                  itemControl: {
                    defaultValue: {
                      color: "#FFFFFF",
                      fontId: "inter",
                      fontSize: 16,
                      fontWeight: "400",
                      letterSpacing: "normal",
                      lineHeight: "normal",
                      opacity: 100,
                      textCase: "original",
                    },
                    label: "Font",
                    type: "fontPicker",
                  },
                  label: "Text styles",
                  minItems: 1,
                  target: "text.styles",
                  type: "collectionActions",
                },
              },
              title: "Typography",
            },
          ],
          title: "Controls",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);

    fireEvent.click(screen.getByRole("button", { name: "Pick Color" }));

    const surface = await waitFor(() => {
      const nextSurface = container.ownerDocument.body.querySelector<HTMLElement>(
        '[data-slot="style-guide-color-surface"]',
      );
      if (!nextSurface) {
        throw new Error("Expected color surface to be open.");
      }
      return nextSurface;
    });

    const surfaceRect = {
      bottom: 100,
      height: 100,
      left: 0,
      right: 100,
      toJSON: () => ({}),
      top: 0,
      width: 100,
      x: 0,
      y: 0,
    } as DOMRect;
    Object.defineProperty(surface, "getBoundingClientRect", {
      configurable: true,
      value: () => surfaceRect,
    });

    fireEvent.pointerDown(surface, {
      buttons: 1,
      clientX: 72,
      clientY: 28,
      pointerId: 1,
    });

    expect(
      container.ownerDocument.body.querySelector('[data-slot="style-guide-color-surface"]'),
    ).toBeTruthy();

    const values = JSON.parse(screen.getByTestId("values-json").textContent ?? "{}");

    expect(values["text.styles"][0].color).not.toBe("#FFFFFF");
  });
});
