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

describe("ControlsPanel curves", () => {
  it("renders single curves without RGB channel tabs", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                easing: {
                  defaultValue: {
                    activeChannel: "RGB",
                    points: {
                      RGB: [
                        { x: 0, y: 0 },
                        { x: 1, y: 1 },
                      ],
                    },
                  },
                  label: "Easing",
                  target: "animation.easing",
                  type: "curves",
                  variant: "single",
                },
                speed: {
                  defaultValue: 1,
                  label: "Speed",
                  max: 2,
                  min: 0,
                  target: "animation.speed",
                  type: "slider",
                },
              },
              title: "Motion",
            },
          ],
          title: "Controls",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);

    expect(screen.getByRole("img", { name: "Easing curve editor" })).toBeTruthy();
    expect(
      screen
        .getAllByText("Easing")
        .some((element) => element.closest("[data-control-field-label]")),
    ).toBeTruthy();
    expect(
      screen
        .getByRole("img", { name: "Easing curve editor" })
        .closest("[data-control-item-compound-context]"),
    ).toBeNull();
    expect(
      container.querySelector('[data-curve-interpolation="monotone"]'),
    ).toBeTruthy();
    expect(screen.queryByText("RGB")).toBeNull();
    expect(screen.queryByText("R")).toBeNull();
    expect(screen.queryByText("G")).toBeNull();
    expect(screen.queryByText("B")).toBeNull();
  });

  it("keeps RGB curves as sectioned compound controls with channel tabs", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                curves: {
                  defaultValue: {
                    activeChannel: "RGB",
                    points: {
                      B: [
                        { x: 0, y: 0 },
                        { x: 1, y: 1 },
                      ],
                      G: [
                        { x: 0, y: 0 },
                        { x: 1, y: 1 },
                      ],
                      R: [
                        { x: 0, y: 0 },
                        { x: 1, y: 1 },
                      ],
                      RGB: [
                        { x: 0, y: 0 },
                        { x: 1, y: 1 },
                      ],
                    },
                  },
                  label: "Tone curves",
                  target: "tone.curves",
                  type: "curves",
                },
                intensity: {
                  defaultValue: 50,
                  label: "Intensity",
                  max: 100,
                  min: 0,
                  target: "tone.intensity",
                  type: "slider",
                },
              },
              title: "Tone",
            },
          ],
          title: "Controls",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);

    expect(screen.getByText("RGB")).toBeTruthy();
    expect(screen.getByText("R")).toBeTruthy();
    expect(
      container.querySelector('[data-control-section-divider="compound"]'),
    ).toBeTruthy();
  });

  it("passes explicit curve interpolation from schema", () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                toneCurve: {
                  defaultValue: {
                    activeChannel: "RGB",
                    points: {
                      RGB: [
                        { x: 0, y: 0 },
                        { x: 0.2, y: 0.85 },
                        { x: 1, y: 1 },
                      ],
                    },
                  },
                  interpolation: "smooth",
                  label: "Tone curve",
                  target: "tone.curve",
                  type: "curves",
                  variant: "single",
                },
              },
              title: "Tone",
            },
          ],
          title: "Controls",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);

    expect(
      container.querySelector('[data-curve-interpolation="smooth"]'),
    ).toBeTruthy();
  });

  it("selects curve points with pointer events and deletes selected interior points", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: false },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                toneCurve: {
                  defaultValue: {
                    activeChannel: "RGB",
                    points: {
                      RGB: [
                        { x: 0, y: 0 },
                        { x: 0.5, y: 0.5 },
                        { x: 1, y: 1 },
                      ],
                    },
                  },
                  label: "Tone curve",
                  target: "tone.curve",
                  type: "curves",
                  variant: "single",
                },
              },
              title: "Tone",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);
    const point = screen.getByRole("button", { name: "Curve point 2" });

    fireEvent.pointerDown(point, { pointerId: 1 });
    fireEvent.pointerUp(point, { pointerId: 1 });

    await waitFor(() => expect(point.getAttribute("aria-pressed")).toBe("true"));

    fireEvent.keyDown(point, { key: "Delete" });

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

      expect(values["tone.curve"].points.RGB).toEqual([
        { x: 0, y: 0 },
        { x: 1, y: 1 },
      ]);
    });
  });
});
