import { z } from 'zod';

const logLevelSchema = z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent']);

const appEnvSchema = z.enum(['development', 'test', 'staging', 'production']);

export const configSchema = z.object({
  APP_NAME: z.string().default('HexaHost GameCloud'),
  APP_ENV: appEnvSchema.default('development'),
  APP_URL: z.string().url(),
  API_URL: z.string().url(),
  DATABASE_URL: z.string().min(1),
  REDIS_URL: z.string().min(1),
  SESSION_SECRET: z.string().min(32),
  LOG_LEVEL: logLevelSchema.default('info'),
  API_PORT: z.coerce.number().int().min(1).max(65535).default(3001),
  WORKER_PORT: z.coerce.number().int().min(1).max(65535).default(3002),
  NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
});

export type AppConfig = z.infer<typeof configSchema>;

function readEnv(): Record<string, string | undefined> {
  return { ...process.env };
}

export function loadConfig(env: Record<string, string | undefined> = readEnv()): AppConfig {
  return configSchema.parse({
    APP_NAME: env['APP_NAME'],
    APP_ENV: env['APP_ENV'],
    APP_URL: env['APP_URL'],
    API_URL: env['API_URL'],
    DATABASE_URL: env['DATABASE_URL'],
    REDIS_URL: env['REDIS_URL'],
    SESSION_SECRET: env['SESSION_SECRET'],
    LOG_LEVEL: env['LOG_LEVEL'],
    API_PORT: env['API_PORT'],
    WORKER_PORT: env['WORKER_PORT'],
    NODE_ENV: env['NODE_ENV'],
  });
}

export function validateConfig(env: Record<string, string | undefined> = readEnv()): AppConfig {
  const requiredKeys = [
    'APP_URL',
    'API_URL',
    'DATABASE_URL',
    'REDIS_URL',
    'SESSION_SECRET',
  ] as const;

  const missing = requiredKeys.filter((key) => !env[key] || env[key]!.trim() === '');

  if (missing.length > 0) {
    throw new Error(
      `Missing required environment variables: ${missing.join(', ')}`,
    );
  }

  const result = configSchema.safeParse({
    APP_NAME: env['APP_NAME'],
    APP_ENV: env['APP_ENV'],
    APP_URL: env['APP_URL'],
    API_URL: env['API_URL'],
    DATABASE_URL: env['DATABASE_URL'],
    REDIS_URL: env['REDIS_URL'],
    SESSION_SECRET: env['SESSION_SECRET'],
    LOG_LEVEL: env['LOG_LEVEL'],
    API_PORT: env['API_PORT'],
    WORKER_PORT: env['WORKER_PORT'],
    NODE_ENV: env['NODE_ENV'],
  });

  if (!result.success) {
    const issues = result.error.issues
      .map((issue) => `${issue.path.join('.')}: ${issue.message}`)
      .join('; ');
    throw new Error(`Invalid configuration: ${issues}`);
  }

  return result.data;
}

let cachedConfig: AppConfig | undefined;

export function getConfig(): AppConfig {
  if (!cachedConfig) {
    cachedConfig = validateConfig();
  }
  return cachedConfig;
}

export function resetConfigCache(): void {
  cachedConfig = undefined;
}
