import { z } from "zod";
import type { AnalyticsProviders } from "@/observability/analytics/types";

const boolish = z
  .enum(["true", "false", "1", "0"])
  .transform((v) => v === "true" || v === "1");

const EnvSchema = z.object({
  NODE_ENV: z.enum(["development", "test", "testing", "staging", "production"]).default("development"),
  BUILD_TARGET: z.enum(["standalone", "remote"]).default("standalone"),
  PROD_ORIGIN: z.string().url().default("https://flights.test.aeroflot.ru"),
  // Same-origin /api — proxied upstream to https://flights.test.aeroflot.ru.
  // In dev, scripts/dev-server.mjs runs an Express+curl proxy on :8080 that
  // bypasses CORS and the WAF TLS-fingerprint filter. In production, the
  // reverse proxy / CDN forwards /api to the real host. Deployments that
  // call the API directly (no proxy) must set API_BASE_URL explicitly.
  API_BASE_URL: z.string().url().default("http://localhost:8080/api"),
  SIGNALR_HUB_URL: z.string().url().default("http://platform.yc.webzavod.ru/tracker/hub"),
  OTEL_EXPORTER_OTLP_ENDPOINT: z.string().url().optional(),
  OTEL_EXPORTER_OTLP_HEADERS: z.string().optional(),
  LOGS_ENDPOINT: z.string().url().optional(),
  ANALYTICS_METRICA: boolish.default("false"),
  ANALYTICS_CTM: boolish.default("false"),
  ANALYTICS_VARIOCUBE: boolish.default("false"),
  ANALYTICS_DYNATRACE: boolish.default("false"),
  FEATURE_FLIGHTS_MAP: boolish.default("true"),
  VERSION: z.string().min(1).default("dev"),
});

type RawEnv = z.infer<typeof EnvSchema>;

export interface Env {
  NODE_ENV: RawEnv["NODE_ENV"];
  BUILD_TARGET: RawEnv["BUILD_TARGET"];
  PROD_ORIGIN: string;
  API_BASE_URL: string;
  SIGNALR_HUB_URL: string;
  OTEL_EXPORTER_OTLP_ENDPOINT?: string;
  OTEL_EXPORTER_OTLP_HEADERS?: string;
  LOGS_ENDPOINT?: string;
  ANALYTICS_ENABLED: AnalyticsProviders;
  FEATURE_FLIGHTS_MAP: boolean;
  VERSION: string;
}

let cached: Env | undefined;

export function getEnv(): Env {
  if (cached) return cached;

  // In the browser, process.env is not available (Rspack doesn't replace
  // bracket-notation access). Fall back to an SSR-injected window.__ENV__
  // or sensible development defaults.
  const envSource =
    typeof process !== "undefined" && process.env
      ? process.env
      : typeof window !== "undefined" && (window as unknown as Record<string, unknown>)["__ENV__"]
        ? (window as unknown as Record<string, unknown>)["__ENV__"] as Record<string, string>
        : {};

  const parsed = EnvSchema.safeParse(envSource);
  if (!parsed.success) {
    const details = parsed.error.issues
      .map((i) => `${i.path.join(".")}: ${i.message}`)
      .join("; ");
    throw new Error(`Invalid environment configuration: ${details}`);
  }

  const raw = parsed.data;
  const result: Env = {
    NODE_ENV: raw.NODE_ENV,
    BUILD_TARGET: raw.BUILD_TARGET,
    PROD_ORIGIN: raw.PROD_ORIGIN,
    API_BASE_URL: raw.API_BASE_URL,
    SIGNALR_HUB_URL: raw.SIGNALR_HUB_URL,
    ANALYTICS_ENABLED: {
      metrica: raw.ANALYTICS_METRICA,
      ctm: raw.ANALYTICS_CTM,
      variocube: raw.ANALYTICS_VARIOCUBE,
      dynatrace: raw.ANALYTICS_DYNATRACE,
    },
    FEATURE_FLIGHTS_MAP: raw.FEATURE_FLIGHTS_MAP,
    VERSION: raw.VERSION,
  };
  if (raw.OTEL_EXPORTER_OTLP_ENDPOINT !== undefined) {
    result.OTEL_EXPORTER_OTLP_ENDPOINT = raw.OTEL_EXPORTER_OTLP_ENDPOINT;
  }
  if (raw.OTEL_EXPORTER_OTLP_HEADERS !== undefined) {
    result.OTEL_EXPORTER_OTLP_HEADERS = raw.OTEL_EXPORTER_OTLP_HEADERS;
  }
  if (raw.LOGS_ENDPOINT !== undefined) {
    result.LOGS_ENDPOINT = raw.LOGS_ENDPOINT;
  }
  cached = result;
  return result;
}

/**
 * Test-only: resets the module-level cache so tests can mutate process.env
 * and re-read. Do NOT call this from production code.
 */
export function __resetEnvCacheForTests(): void {
  cached = undefined;
}
