import { z } from 'zod';

const urlOptional = z.string().url().optional();
const stringOptional = z.string().optional();

const publicEnvSchema = z.object({
  NEXT_PUBLIC_SITE_URL: urlOptional,
  NEXT_PUBLIC_API_BASE_URL: urlOptional,

  NEXT_PUBLIC_SITE_NAME: stringOptional,
  NEXT_PUBLIC_SUPPORT_EMAIL: stringOptional,
  NEXT_PUBLIC_SPONSOR_EMAIL: stringOptional,

  NEXT_PUBLIC_LEGAL_COMPANY_NAME: stringOptional,
  NEXT_PUBLIC_LEGAL_VAT_ID: stringOptional,
  NEXT_PUBLIC_LEGAL_REGISTERED_COUNTRY: stringOptional,
  NEXT_PUBLIC_LEGAL_REGISTERED_ADDRESS: stringOptional,

  NEXT_PUBLIC_DISCORD_URL: stringOptional,
  NEXT_PUBLIC_X_URL: stringOptional,
});

const serverEnvSchema = z.object({
  API_BASE_URL: urlOptional,
  KV_REST_API_URL: urlOptional,
  KV_REST_API_TOKEN: stringOptional,

  CI: stringOptional,
  DOCKER: stringOptional,
  NODE_ENV: z.enum(['development', 'production', 'test']).optional(),
});

export type WebsitePublicEnv = z.infer<typeof publicEnvSchema>;
export type WebsiteServerEnv = z.infer<typeof serverEnvSchema>;

function formatZodIssues(issues: z.ZodIssue[]): string {
  return issues
    .map((issue) => {
      const path = issue.path.join('.') || '(root)';
      return `${path}: ${issue.message}`;
    })
    .join('; ');
}

/**
 * Parses Website env vars (server-side safe).
 * Only validates the variables we explicitly support.
 */
export function getWebsiteServerEnv(): WebsiteServerEnv {
  const result = serverEnvSchema.safeParse(process.env);
  if (!result.success) {
    throw new Error(`Invalid website server env: ${formatZodIssues(result.error.issues)}`);
  }
  return result.data;
}

/**
 * Parses Website public env vars (safe on both server + client).
 * Note: on the client, only `NEXT_PUBLIC_*` vars are actually present.
 */
export function getWebsitePublicEnv(): WebsitePublicEnv {
  const result = publicEnvSchema.safeParse(process.env);
  if (!result.success) {
    throw new Error(`Invalid website public env: ${formatZodIssues(result.error.issues)}`);
  }
  return result.data;
}

export function isTruthyEnv(value: string | undefined): boolean {
  if (!value) return false;
  return value !== '0' && value.toLowerCase() !== 'false';
}

/**
 * Matches the semantics used in [`getWebsiteApiBaseUrl()`](apps/website/lib/config/apiBaseUrl.ts:6).
 */
export function isTestLikeEnvironment(): boolean {
  const { NODE_ENV, CI, DOCKER } = getWebsiteServerEnv();
  return NODE_ENV === 'test' || CI === 'true' || DOCKER === 'true';
}

export function isProductionEnvironment(): boolean {
  return getWebsiteServerEnv().NODE_ENV === 'production';
}

export function isKvConfigured(): boolean {
  const { KV_REST_API_URL, KV_REST_API_TOKEN } = getWebsiteServerEnv();
  return Boolean(KV_REST_API_URL && KV_REST_API_TOKEN);
}

export function assertKvConfiguredInProduction(): void {
  if (isProductionEnvironment() && !isKvConfigured()) {
    throw new Error('Missing KV_REST_API_URL/KV_REST_API_TOKEN in production environment');
  }
}