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

import { loadEnv, resetEnvCacheForTesting } from "./env.ts";

const minimalValidEnv: NodeJS.ProcessEnv = {
  SUPABASE_URL: "https://example.supabase.co",
  SUPABASE_SERVICE_ROLE_KEY: "service-role-key",
};

afterEach(() => {
  resetEnvCacheForTesting();
});

describe("loadEnv", () => {
  it("accepts a minimal valid env and applies defaults", () => {
    const env = loadEnv(minimalValidEnv);

    expect(env.supabaseUrl).toBe("https://example.supabase.co");
    expect(env.supabaseKey).toBe("service-role-key");
    expect(env.automationPort).toBe(3030);
    expect(env.standardizeConcurrency).toBe(1);
    expect(env.llmQueueMinIntervalMs).toBe(3000);
    expect(env.llmRetryMaxAttempts).toBe(4);
    expect(env.llmRetryBaseDelayMs).toBe(1500);
    expect(env.promptEnv).toBe("prod");
    expect(env.promptCacheTtlMs).toBe(300_000);
    expect(env.llmBaseUrl).toBeUndefined();
    expect(env.llmApiKey).toBeUndefined();
  });

  it("falls back to VITE_SUPABASE_URL when SUPABASE_URL is missing", () => {
    const env = loadEnv({
      VITE_SUPABASE_URL: "https://vite.supabase.co",
      SUPABASE_SERVICE_ROLE_KEY: "service-role-key",
    });
    expect(env.supabaseUrl).toBe("https://vite.supabase.co");
  });

  it("treats empty strings as missing for optional vars", () => {
    const env = loadEnv({
      ...minimalValidEnv,
      LLM_BASE_URL: "  ",
      LLM_API_KEY: "",
    });
    expect(env.llmBaseUrl).toBeUndefined();
    expect(env.llmApiKey).toBeUndefined();
  });

  it("parses numeric env vars and rejects non-positive ports", () => {
    expect(() =>
      loadEnv({ ...minimalValidEnv, AUTOMATION_PORT: "0" }),
    ).toThrow(/automationPort/);
    expect(() =>
      loadEnv({ ...minimalValidEnv, AUTOMATION_PORT: "not-a-number" }),
    ).toThrow(/automationPort/);
  });

  it("falls back to default when numeric env var is empty", () => {
    const env = loadEnv({
      ...minimalValidEnv,
      AUTOMATION_PORT: "  ",
      LLM_RETRY_MAX_ATTEMPTS: "",
    });
    expect(env.automationPort).toBe(3030);
    expect(env.llmRetryMaxAttempts).toBe(4);
  });

  it("rejects negative llmQueueMinIntervalMs", () => {
    expect(() =>
      loadEnv({ ...minimalValidEnv, LLM_QUEUE_MIN_INTERVAL_MS: "-1" }),
    ).toThrow(/llmQueueMinIntervalMs/);
  });

  it("throws a helpful error when Supabase config is missing", () => {
    expect(() => loadEnv({})).toThrow(/SUPABASE_URL/);
  });

  it("memoizes the result across calls", () => {
    const a = loadEnv(minimalValidEnv);
    const b = loadEnv({
      ...minimalValidEnv,
      AUTOMATION_PORT: "9999", // ignored — cached value already returned
    });
    expect(a).toBe(b);
    expect(b.automationPort).toBe(3030);
  });

  it("re-parses after resetEnvCacheForTesting()", () => {
    loadEnv(minimalValidEnv);
    resetEnvCacheForTesting();
    const env = loadEnv({ ...minimalValidEnv, AUTOMATION_PORT: "4040" });
    expect(env.automationPort).toBe(4040);
  });
});
