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

describe("ControlsPanel conditional control visibility", () => {
  it("disables a dependent switch through disabledWhen", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                background: {
                  defaultValue: false,
                  label: "Background",
                  target: "export.includeBackground",
                  type: "switch",
                },
                infinity: {
                  defaultValue: false,
                  disabledWhen: {
                    equals: false,
                    target: "export.includeBackground",
                  },
                  label: "Infinity canvas",
                  target: "fixture.infinity",
                  type: "switch",
                },
              },
              title: "Setup",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);
    const backgroundField = screen
      .getByText("Background")
      .closest<HTMLElement>('[data-slot="field"]');
    const infinityField = screen
      .getByText("Infinity canvas")
      .closest<HTMLElement>('[data-slot="field"]');
    const backgroundSwitch =
      backgroundField?.querySelector<HTMLElement>('[role="switch"]');
    const infinitySwitch =
      infinityField?.querySelector<HTMLElement>('[role="switch"]');

    expect(infinitySwitch?.hasAttribute("data-disabled")).toBe(true);
    fireEvent.click(backgroundSwitch!);
    await waitFor(() => {
      expect(infinitySwitch?.hasAttribute("data-disabled")).toBe(false);
    });
  });

  it("disables sliders from dependent mode values", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                fillMode: {
                  defaultValue: "full",
                  label: "Fill mode",
                  options: [
                    { label: "Full", value: "full" },
                    { label: "Partial", value: "partial" },
                  ],
                  target: "distribution.fillMode",
                  type: "segmented",
                },
                fillAmount: {
                  defaultValue: 41,
                  disabledWhen: {
                    equals: "full",
                    target: "distribution.fillMode",
                  },
                  label: "Fill level",
                  max: 100,
                  min: 0,
                  step: 1,
                  target: "distribution.fillAmount",
                  type: "slider",
                  unit: "%",
                },
                clusterBias: {
                  defaultValue: 63,
                  disabledWhen: {
                    equals: "full",
                    target: "distribution.fillMode",
                  },
                  label: "Islands",
                  max: 100,
                  min: 0,
                  step: 1,
                  target: "distribution.clusterBias",
                  type: "slider",
                  unit: "%",
                },
              },
              title: "Distribution",
            },
          ],
          title: "Token Grid",
        },
      },
    });

    const { container } = renderControlsPanelWithSchema(schema);
    const fillLevelField = screen.getByText("Fill level").closest('[data-slot="field"]');
    const islandsField = screen.getByText("Islands").closest('[data-slot="field"]');

    expect(fillLevelField?.getAttribute("data-disabled")).toBe("true");
    expect(islandsField?.getAttribute("data-disabled")).toBe("true");
    expect(
      container.querySelectorAll<HTMLElement>('[data-slot="slider"][data-disabled]'),
    ).toHaveLength(2);

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

    await waitFor(() => {
      expect(fillLevelField?.getAttribute("data-disabled")).not.toBe("true");
      expect(islandsField?.getAttribute("data-disabled")).not.toBe("true");
    });
    expect(
      container.querySelectorAll<HTMLElement>('[data-slot="slider"][data-disabled]'),
    ).toHaveLength(0);
  });

  it("renders only applicable controls and preserves hidden values", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                identityMode: {
                  applicability: { mode: "always" },
                  defaultValue: "text",
                  label: "Identity",
                  options: [
                    { label: "Text", value: "text" },
                    { label: "Logo", value: "logo" },
                  ],
                  target: "coBrand.identityMode",
                  type: "segmented",
                },
                partnerName: {
                  applicability: {
                    all: [
                      { equals: "text", target: "coBrand.identityMode" },
                      { equals: true, target: "coBrand.partnerEnabled" },
                    ],
                    mode: "conditional",
                  },
                  defaultValue: "tRPC",
                  label: "Partner",
                  target: "coBrand.partnerName",
                  type: "text",
                },
                partnerLogo: {
                  applicability: {
                    all: [
                      { equals: "logo", target: "coBrand.identityMode" },
                      { equals: true, target: "coBrand.partnerEnabled" },
                    ],
                    mode: "conditional",
                  },
                  defaultValue: "logo.svg",
                  label: "Partner logo",
                  target: "coBrand.partnerLogo",
                  type: "text",
                },
              },
              title: "Partner Lockup",
            },
          ],
          title: "Cover Builder",
        },
      },
    });

    renderControlsPanelWithSchema(schema, {}, {
      values: { "coBrand.partnerEnabled": true },
    });

    const partnerInput = screen.getByDisplayValue("tRPC");

    expect(screen.getByText("Partner")).toBeTruthy();
    expect(screen.queryByText("Partner logo")).toBeNull();

    fireEvent.change(partnerInput, { target: { value: "Databricks" } });
    fireEvent.blur(partnerInput);

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

    await waitFor(() => {
      expect(screen.queryByText("Partner")).toBeNull();
      expect(screen.getByText("Partner logo")).toBeTruthy();
    });

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

    await waitFor(() => {
      expect(screen.getByDisplayValue("Databricks")).toBeTruthy();
      expect(screen.queryByText("Partner logo")).toBeNull();
    });
  });

  it("renders count-dependent controls through numeric applicability", () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                shadeCount: {
                  applicability: { mode: "always" },
                  defaultValue: 2,
                  label: "Shades",
                  max: 5,
                  min: 1,
                  step: 1,
                  target: "shapes.shadeCount",
                  type: "slider",
                  variant: "discrete",
                },
                shade1: {
                  applicability: { mode: "always" },
                  defaultValue: { hex: "#FFFFFF" },
                  label: "Shade 1",
                  target: "shapes.color1",
                  type: "color",
                },
                shade2: {
                  applicability: {
                    all: [
                      {
                        greaterThanOrEqual: 2,
                        target: "shapes.shadeCount",
                      },
                    ],
                    mode: "conditional",
                  },
                  defaultValue: { hex: "#DDDDDD" },
                  label: "Shade 2",
                  target: "shapes.color2",
                  type: "color",
                },
                shade3: {
                  applicability: {
                    all: [
                      {
                        greaterThanOrEqual: 3,
                        target: "shapes.shadeCount",
                      },
                    ],
                    mode: "conditional",
                  },
                  defaultValue: { hex: "#BBBBBB" },
                  label: "Shade 3",
                  target: "shapes.color3",
                  type: "color",
                },
              },
              title: "Shapes",
            },
          ],
          title: "Pattern Controls",
        },
      },
    });

    const { unmount } = renderControlsPanelWithSchema(schema);

    expect(screen.getByText("Shade 1")).toBeTruthy();
    expect(screen.getByText("Shade 2")).toBeTruthy();
    expect(screen.queryByText("Shade 3")).toBeNull();

    unmount();

    renderControlsPanelWithSchema(schema, {}, {
      values: {
        "shapes.shadeCount": 3,
      },
    });

    expect(screen.getByText("Shade 1")).toBeTruthy();
    expect(screen.getByText("Shade 2")).toBeTruthy();
    expect(screen.getByText("Shade 3")).toBeTruthy();
  });

  it("skips sections that do not match visibleWhen", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                template: {
                  defaultValue: "editorial",
                  label: "Template",
                  options: [
                    { label: "Editorial", value: "editorial" },
                    { label: "Code", value: "code" },
                  ],
                  target: "cover.templateId",
                  type: "segmented",
                },
              },
              title: "Cover Format",
            },
            {
              controls: {
                codeBody: {
                  defaultValue: "const value = true;",
                  label: "Code",
                  target: "code.body",
                  type: "code",
                },
              },
              title: "Code Sample",
              visibleWhen: {
                equals: "code",
                target: "cover.templateId",
              },
            },
          ],
          title: "Cover Builder",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    expect(screen.queryByText("Code Sample")).toBeNull();
    expect(screen.queryByDisplayValue("const value = true;")).toBeNull();

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

    await waitFor(() => {
      expect(screen.getByText("Code Sample")).toBeTruthy();
      expect(screen.getByDisplayValue("const value = true;")).toBeTruthy();
    });
  });

  it("skips sections when every control inside is hidden by visibleWhen", async () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                identityMode: {
                  defaultValue: "text",
                  label: "Identity",
                  options: [
                    { label: "Text", value: "text" },
                    { label: "Logo", value: "logo" },
                  ],
                  target: "coBrand.identityMode",
                  type: "segmented",
                },
              },
              title: "Identity",
            },
            {
              controls: {
                logoScale: {
                  defaultValue: 80,
                  label: "Scale",
                  target: "coBrand.logoScale",
                  type: "slider",
                  visibleWhen: {
                    equals: "logo",
                    target: "coBrand.identityMode",
                  },
                },
                logoRadius: {
                  defaultValue: 12,
                  label: "Radius",
                  target: "coBrand.logoRadius",
                  type: "slider",
                  visibleWhen: {
                    equals: "logo",
                    target: "coBrand.identityMode",
                  },
                },
              },
              title: "Logo Options",
            },
          ],
          title: "Cover Builder",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    expect(screen.queryByText("Logo Options")).toBeNull();
    expect(screen.queryByText("Scale")).toBeNull();
    expect(screen.queryByText("Radius")).toBeNull();

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

    await waitFor(() => {
      expect(screen.getByText("Logo Options")).toBeTruthy();
      expect(screen.getByText("Scale")).toBeTruthy();
      expect(screen.getByText("Radius")).toBeTruthy();
    });
  });
});
