import { afterEach, describe, expect, it, vi } from "vitest";

import { getApiConfig } from "@/core/net/config/api_config";

const CONFIG_ENV_KEYS = [
  "NEXT_PUBLIC_API_BASE_URL",
  "NEXT_PUBLIC_WS_BASE_URL",
  "NEXT_PUBLIC_API_CONNECT_TIMEOUT",
  "NEXT_PUBLIC_API_RECEIVE_TIMEOUT",
  "NEXT_PUBLIC_API_SEND_TIMEOUT",
] as const;

afterEach(() => {
  vi.unstubAllEnvs();
});

describe("getApiConfig", () => {
  it("keeps local defaults in development", () => {
    vi.stubEnv("NEXT_PUBLIC_APP_ENV", "development");
    unsetConfigEnv();

    expect(getApiConfig()).toEqual({
      baseUrl: "http://172.16.48.49:3002",
      wsUrl: "ws://172.16.48.49:3002/ws",
      connectTimeout: 30_000,
      receiveTimeout: 60_000,
      sendTimeout: 30_000,
    });
  });

  it.each(["test", "production"])(
    "requires explicit service URLs in %s",
    (appEnv) => {
      vi.stubEnv("NEXT_PUBLIC_APP_ENV", appEnv);
      unsetConfigEnv();

      expect(() => getApiConfig()).toThrow(
        `[ApiConfig] Invalid ${appEnv} configuration`,
      );
    },
  );

  it("parses an explicit non-development configuration", () => {
    vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
    vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "https://api.example.test");
    vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "wss://api.example.test/ws");
    vi.stubEnv("NEXT_PUBLIC_API_CONNECT_TIMEOUT", "1000");
    vi.stubEnv("NEXT_PUBLIC_API_RECEIVE_TIMEOUT", "2000");
    vi.stubEnv("NEXT_PUBLIC_API_SEND_TIMEOUT", "3000");

    expect(getApiConfig()).toEqual({
      baseUrl: "https://api.example.test",
      wsUrl: "wss://api.example.test/ws",
      connectTimeout: 1000,
      receiveTimeout: 2000,
      sendTimeout: 3000,
    });
  });

  it.each(["not-a-number", "0", "-1", "1.5"])(
    "rejects invalid timeout %s",
    (timeout) => {
      vi.stubEnv("NEXT_PUBLIC_APP_ENV", "test");
      vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "https://api.example.test");
      vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "wss://api.example.test/ws");
      vi.stubEnv("NEXT_PUBLIC_API_CONNECT_TIMEOUT", timeout);

      expect(() => getApiConfig()).toThrow(/connectTimeout/);
    },
  );

  it("rejects URLs with the wrong protocol", () => {
    vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
    vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "ftp://api.example.test");
    vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "https://api.example.test/ws");

    expect(() => getApiConfig()).toThrow(/baseUrl.*wsUrl/);
  });
});

function unsetConfigEnv(): void {
  for (const key of CONFIG_ENV_KEYS) vi.stubEnv(key, undefined);
}
