import { describe, it, expect, vi } from "vitest";
import { runVariablesConverter } from "./run";
import type { ToolContext } from "../../core/plugins/plugin-types";

describe("Variables Converter", () => {
  const mockContext: ToolContext = {
    signal: new AbortController().signal,
    reportProgress: vi.fn(),
    logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
  };

  it("should convert dot notation to constant case and others", async () => {
    const result = await runVariablesConverter(
      { text: "a.b.c" },
      { toFormat: "constant" },
      mockContext
    );
    expect(result.type).toBe("json");
    const val = (result as { type: "json"; value: Record<string, unknown> }).value;
    expect(val.constant).toBe("A_B_C");
    expect(val.dot).toBe("a.b.c");
    expect(val.camel).toBe("aBC");
    expect(val.pascal).toBe("ABC");
    expect(val.snake).toBe("a_b_c");
    expect(val.kebab).toBe("a-b-c");
    expect(val.primary).toBe("A_B_C");
  });

  it("should convert screaming snake case (constant) to dot notation", async () => {
    const result = await runVariablesConverter(
      { text: "USER_PROFILE_NAME" },
      { toFormat: "dot" },
      mockContext
    );
    const val = (result as { type: "json"; value: Record<string, unknown> }).value;
    expect(val.constant).toBe("USER_PROFILE_NAME");
    expect(val.dot).toBe("user.profile.name");
    expect(val.camel).toBe("userProfileName");
    expect(val.pascal).toBe("UserProfileName");
    expect(val.primary).toBe("user.profile.name");
  });

  it("should handle camelCase inputs correctly", async () => {
    const result = await runVariablesConverter(
      { text: "myApiKey" },
      { toFormat: "kebab" },
      mockContext
    );
    const val = (result as { type: "json"; value: Record<string, unknown> }).value;
    expect(val.constant).toBe("MY_API_KEY");
    expect(val.kebab).toBe("my-api-key");
    expect(val.primary).toBe("my-api-key");
  });

  it("should handle auto mode detection correctly", async () => {
    // 1. Dot notation auto-converts to Constant Case
    const resDot = await runVariablesConverter(
      { text: "a.b.c" },
      { toFormat: "auto" },
      mockContext
    );
    expect((resDot as { type: "json"; value: Record<string, unknown> }).value.primary).toBe("A_B_C");

    // 2. Kebab notation auto-converts to Constant Case
    const resKebab = await runVariablesConverter(
      { text: "a-b-c" },
      { toFormat: "auto" },
      mockContext
    );
    expect((resKebab as { type: "json"; value: Record<string, unknown> }).value.primary).toBe("A_B_C");

    // 3. Constant notation auto-converts to Dot Notation
    const resConstant = await runVariablesConverter(
      { text: "A_B_C" },
      { toFormat: "auto" },
      mockContext
    );
    expect((resConstant as { type: "json"; value: Record<string, unknown> }).value.primary).toBe("a.b.c");
  });

  it("should throw on empty input", async () => {
    await expect(
      runVariablesConverter({ text: "" }, { toFormat: "auto" }, mockContext)
    ).rejects.toThrow("No variable name provided");
  });
});
