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

describe("ControlsPanel text input controls", () => {
  it("renders editable text inputs and textareas with caret cursor affordance", () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                prompt: {
                  defaultValue: "Short prompt",
                  label: "Prompt",
                  target: "generation.prompt",
                  type: "text",
                },
                instructions: {
                  defaultValue: "Long prompt instructions",
                  label: "Instructions",
                  target: "generation.instructions",
                  type: "code",
                },
              },
              title: "Text",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    expect(screen.getByDisplayValue("Short prompt").className).toContain("cursor-text");
    expect(screen.getByDisplayValue("Long prompt instructions").className).toContain(
      "cursor-text",
    );
    expect(screen.getByDisplayValue("Long prompt instructions").className).toContain(
      "max-h-[calc(12lh+12px)]",
    );
    expect(screen.getByDisplayValue("Long prompt instructions").className).toContain(
      "overflow-y-auto",
    );
  });

  it("preserves newline characters in code textarea values by default", () => {
    const initialInstructions = "First line\nSecond line";
    const editedInstructions = "Alpha\nBeta\nGamma";
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                instructions: {
                  defaultValue: initialInstructions,
                  label: "Instructions",
                  target: "generation.instructions",
                  type: "code",
                },
              },
              title: "Text",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    const textarea = screen.getByLabelText("Instructions") as HTMLTextAreaElement;

    expect(textarea.tagName).toBe("TEXTAREA");
    expect(textarea.value).toBe(initialInstructions);

    fireEvent.change(textarea, { target: { value: editedInstructions } });

    expect(textarea.value).toBe(editedInstructions);
    expect(screen.getByTestId("values-json").textContent).toContain(
      `"generation.instructions":${JSON.stringify(editedInstructions)}`,
    );
  });

  it("applies text input values while typing", () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                prompt: {
                  defaultValue: "Initial prompt",
                  label: "Prompt",
                  target: "generation.prompt",
                  type: "text",
                },
              },
              title: "Text",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    const input = screen.getByDisplayValue("Initial prompt") as HTMLInputElement;

    fireEvent.change(input, { target: { value: "Live prompt" } });

    expect(input.value).toBe("Live prompt");
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"generation.prompt":"Live prompt"',
    );
  });

  it("commits setting text inputs on blur or Enter", () => {
    const schema = defineToolcraft({
      canvas: { enabled: true },
      panels: {
        controls: {
          sections: [
            {
              controls: {
                fontSize: {
                  commitMode: "setting",
                  defaultValue: "16",
                  label: "Font size",
                  target: "typography.fontSize",
                  type: "text",
                },
              },
              title: "Typography",
            },
          ],
          title: "Controls",
        },
      },
    });

    renderControlsPanelWithSchema(schema);

    const input = screen.getByDisplayValue("16") as HTMLInputElement;

    fireEvent.change(input, { target: { value: "24" } });
    expect(input.value).toBe("24");
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"typography.fontSize":"16"',
    );

    fireEvent.blur(input);
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"typography.fontSize":"24"',
    );

    fireEvent.change(input, { target: { value: "32" } });
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"typography.fontSize":"24"',
    );

    fireEvent.keyDown(input, { code: "Enter", key: "Enter" });
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"typography.fontSize":"32"',
    );

    fireEvent.change(input, { target: { value: "" } });
    expect(input.value).toBe("");

    fireEvent.blur(input);
    expect(screen.getByDisplayValue("16")).toBeTruthy();
    expect(screen.getByTestId("values-json").textContent).toContain(
      '"typography.fontSize":"16"',
    );
  });

  it("applies empty text input values while typing and reset restores defaults", () => {
    renderControlsPanel();

    const promptInput = screen.getByDisplayValue("Initial prompt") as HTMLInputElement;

    fireEvent.change(promptInput, { target: { value: "" } });
    expect(promptInput.value).toBe("");
    expect(screen.getByTestId("prompt-value").textContent).toBe("");

    fireEvent.change(promptInput, { target: { value: "Draft prompt" } });
    expect(screen.getByTestId("prompt-value").textContent).toBe("Draft prompt");

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

    expect(screen.getByDisplayValue("Initial prompt")).toBeTruthy();
    expect(screen.getByTestId("prompt-value").textContent).toBe("Initial prompt");
  });
});
