import defineConfig from "./defineConfig";
import * as path from "node:path";
import { existsSync } from "node:fs";

vi.mock("node:path", async () => {
  const actual = await vi.importActual("node:path");
  return {
    ...actual,
    resolve: vi.fn(),
  };
});

vi.mock("node:fs", () => ({
  existsSync: vi.fn(),
}));

const baseConfigArgs = {
  plugins: [],
  pushBaseUrl: "pushBaseUrl",
  audienceUrl: "audienceUrl",
  authDomain: "authDomain",
  authClientId: "authClientId",
  errorFallbackComponent: "errorFallbackComponent",
  applicationEnvironment: "applicationEnvironment",
  rollbarAccessToken: "rollbarAccessToken",
  previewBaseUrl: "previewBaseUrl",
  modelsSrc: "modelsSrc",
  presetsSrc: "presetsSrc",
};

describe("defineConfig", () => {
  beforeEach(() => {
    vi.mocked(existsSync).mockReturnValue(true);
    const coreRoot = "/embeddable-sdk/packages/core-sdk";
    vi.mocked(path.resolve).mockReturnValue(coreRoot);

    vi.spyOn(process, "cwd").mockReturnValue(
      "/embeddable-sdk/packages/core-sdk",
    );
  });

  it("should return a config object", async () => {
    const config = await defineConfig(baseConfigArgs);

    expect(config).toMatchInlineSnapshot(`
      {
        "applicationEnvironment": "applicationEnvironment",
        "audienceUrl": "audienceUrl",
        "authClientId": "authClientId",
        "authDomain": "authDomain",
        "buildTime": undefined,
        "client": {
          "archiveFile": "/embeddable-sdk/packages/core-sdk",
          "buildDir": "/embeddable-sdk/packages/core-sdk",
          "bundleHash": undefined,
          "componentDir": "/embeddable-sdk/packages/core-sdk",
          "componentLibraries": [],
          "customizationFile": "/embeddable-sdk/packages/core-sdk",
          "errorFallbackComponent": "/embeddable-sdk/packages/core-sdk",
          "globalCss": "/embeddable-sdk/packages/core-sdk",
          "lifecycleHooksFile": "/embeddable-sdk/packages/core-sdk",
          "modelsSrc": "/embeddable-sdk/packages/core-sdk",
          "presetsSrc": "/embeddable-sdk/packages/core-sdk",
          "rollupOptions": {},
          "rootDir": "/embeddable-sdk/packages/core-sdk",
          "srcDir": "/embeddable-sdk/packages/core-sdk",
          "stencilBuild": "/embeddable-sdk/packages/core-sdk",
          "tmpDir": "/embeddable-sdk/packages/core-sdk",
          "viteConfig": {},
        },
        "core": {
          "configsDir": "/embeddable-sdk/packages/core-sdk",
          "rootDir": "/embeddable-sdk/packages/core-sdk",
          "templatesDir": "/embeddable-sdk/packages/core-sdk",
        },
        "dev": {
          "logger": undefined,
          "sys": undefined,
          "watch": false,
        },
        "outputOptions": {
          "typesEntryPointFilename": "embeddable-types-entry-point.js",
        },
        "plugins": [],
        "previewBaseUrl": "previewBaseUrl",
        "pushBaseUrl": "pushBaseUrl",
        "pushComponents": true,
        "pushModels": true,
        "rollbarAccessToken": "rollbarAccessToken",
      }
    `);
  });

  it("throws error for invalid property", () => {
    expect(() =>
      defineConfig({ plugins: [], invalidProp: "INVALID" as any } as any),
    ).toThrow(
      `Invalid Embeddable Configuration: "": Unrecognized key(s) in object: 'invalidProp'}`,
    );
  });

  it("throws error for invalid property value", () => {
    expect(() =>
      defineConfig({ plugins: [], pushBaseUrl: 123 as any } as any),
    ).toThrow(
      `Invalid Embeddable Configuration: "pushBaseUrl": Expected string, received number}`,
    );
  });

  describe("region configuration", () => {
    it("uses legacy-US region by default", () => {
      const config = defineConfig({ plugins: [] });

      expect(config.pushBaseUrl).toBe("https://api.embeddable.com");
      expect(config.audienceUrl).toBe("https://auth.embeddable.com");
      expect(config.previewBaseUrl).toBe("https://app.embeddable.com");
      expect(config.authDomain).toBe("auth.embeddable.com");
      expect(config.authClientId).toBe("dygrSUmI6HmgY5ymVbEAoLDEBxIOyr1V");
    });

    it("configures EU region correctly", () => {
      const config = defineConfig({ plugins: [], region: "EU" });

      expect(config.pushBaseUrl).toBe("https://api.eu.embeddable.com");
      expect(config.audienceUrl).toBe("https://auth.eu.embeddable.com");
      expect(config.previewBaseUrl).toBe("https://app.eu.embeddable.com");
      expect(config.authDomain).toBe("auth.eu.embeddable.com");
      expect(config.authClientId).toBe("6OGPwIQsVmtrBKhNrwAaXhz4ePb0kBGV");
    });

    it("configures US region correctly", () => {
      const config = defineConfig({ plugins: [], region: "US" });

      expect(config.pushBaseUrl).toBe("https://api.us.embeddable.com");
      expect(config.audienceUrl).toBe("https://auth.embeddable.com");
      expect(config.previewBaseUrl).toBe("https://app.us.embeddable.com");
      expect(config.authDomain).toBe("auth.embeddable.com");
      expect(config.authClientId).toBe("dygrSUmI6HmgY5ymVbEAoLDEBxIOyr1V");
    });

    it("allows overriding region-specific values", () => {
      const config = defineConfig({
        plugins: [],
        region: "EU",
        pushBaseUrl: "custom-push-url",
        authClientId: "custom-client-id",
      });

      expect(config.pushBaseUrl).toBe("custom-push-url");
      expect(config.authClientId).toBe("custom-client-id");
      // Other values should still be from EU region
      expect(config.audienceUrl).toBe("https://auth.eu.embeddable.com");
      expect(config.previewBaseUrl).toBe("https://app.eu.embeddable.com");
      expect(config.authDomain).toBe("auth.eu.embeddable.com");
    });

    it("throws error for invalid region", () => {
      expect(() =>
        defineConfig({ plugins: [], region: "INVALID" as any }),
      ).toThrow(
        `Invalid Embeddable Configuration: "region": Invalid literal value, expected "legacy-US"}`,
      );
    });
  });

  describe("push configuration", () => {
    it("defaults pushModels and pushComponents to true", () => {
      const config = defineConfig({ plugins: [] });
      expect(config.pushModels).toBe(true);
      expect(config.pushComponents).toBe(true);
    });

    it("allows overriding pushModels and pushComponents", () => {
      const config = defineConfig({
        plugins: [],
        pushModels: false,
        pushComponents: false,
      });
      expect(config.pushModels).toBe(false);
      expect(config.pushComponents).toBe(false);
    });

    it("allows mixed configuration of pushModels and pushComponents", () => {
      const configModelOnly = defineConfig({
        plugins: [],
        pushModels: true,
        pushComponents: false,
      });
      expect(configModelOnly.pushModels).toBe(true);
      expect(configModelOnly.pushComponents).toBe(false);

      const configComponentOnly = defineConfig({
        plugins: [],
        pushModels: false,
        pushComponents: true,
      });
      expect(configComponentOnly.pushModels).toBe(false);
      expect(configComponentOnly.pushComponents).toBe(true);
    });
  });
});
