import 'dotenv/config';
import path from 'path';
import { z } from 'zod';

const envSchema = z.object({
  // Server
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
  PORT: z.coerce.number().default(5000),

  // Database
  DATABASE_URL: z.string().url(),

  // Redis
  REDIS_URL: z.string().default('redis://localhost:6399'),

  // JWT
  JWT_ACCESS_SECRET: z.string().min(32),
  JWT_REFRESH_SECRET: z.string().min(32),
  JWT_ACCESS_EXPIRES_IN: z.string().default('15m'),
  JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),

  // Encryption key for secrets at rest (64 hex chars = 32 bytes for AES-256)
  ENCRYPTION_KEY: z.string().min(64).regex(/^[0-9a-f]+$/i, 'Must be hex-encoded (use: openssl rand -hex 32)'),

  // Initial admin
  INITIAL_ADMIN_EMAIL: z.string().email().default('admin@example.com'),
  INITIAL_ADMIN_PASSWORD: z.string().min(12).default('ChangeMe2025!!'),

  // CORS
  CORS_ORIGINS: z.string().default('http://localhost:5100'),

  // Instance management (resolved by setup.sh; fallback for local dev)
  INSTANCES_BASE_PATH: z.string().default(
    path.resolve(process.cwd(), '..', 'instances')
  ),
  CML_SOURCE_PATH: z.string().default(''),
  CML_GIT_REPO: z.string().default(''),
  CML_GIT_BRANCH: z.string().default('v2'),

  // Port allocation ranges
  PORT_RANGE_API_START: z.coerce.number().default(14000),
  PORT_RANGE_API_END: z.coerce.number().default(14999),
  PORT_RANGE_ADMIN_START: z.coerce.number().default(13000),
  PORT_RANGE_ADMIN_END: z.coerce.number().default(13999),
  PORT_RANGE_POSTGRES_START: z.coerce.number().default(15400),
  PORT_RANGE_POSTGRES_END: z.coerce.number().default(15499),
  PORT_RANGE_NGINX_START: z.coerce.number().default(10000),
  PORT_RANGE_NGINX_END: z.coerce.number().default(10999),
  PORT_RANGE_EMBED_START: z.coerce.number().default(12000),
  PORT_RANGE_EMBED_END: z.coerce.number().default(12499),

  // Container Registry (for provisioned instances)
  GITEA_REGISTRY: z.string().default('gitea.bnkops.com/admin'),
  USE_REGISTRY_IMAGES: z.enum(['true', 'false']).default('true').transform((v) => v === 'true'),
  IMAGE_TAG: z.string().default('latest'),

  // Pangolin (optional — for remote tunnel management)
  PANGOLIN_API_URL: z.string().default(''),
  PANGOLIN_API_KEY: z.string().default(''),
  PANGOLIN_ORG_ID: z.string().default(''),
  PANGOLIN_ENDPOINT: z.string().default(''), // Newt WebSocket URL (may differ from API URL)

  // Health checks
  HEALTH_CHECK_INTERVAL_MS: z.coerce.number().default(300_000), // 5 min (0 to disable)

  // Remote agent defaults
  AGENT_CONNECT_TIMEOUT_MS: z.coerce.number().default(10_000),
  AGENT_REQUEST_TIMEOUT_MS: z.coerce.number().default(30_000),
  AGENT_LONG_OP_TIMEOUT_MS: z.coerce.number().default(600_000), // 10 min for backups/builds
  AGENT_HEALTH_FAILURE_THRESHOLD: z.coerce.number().default(3),

  // Backups
  BACKUP_STORAGE_PATH: z.string().default(
    path.resolve(process.cwd(), '..', 'backups')
  ),
  BACKUP_RETENTION_DAYS: z.coerce.number().default(30),
});

function validateEnv() {
  const result = envSchema.safeParse(process.env);
  if (!result.success) {
    console.error('❌ Invalid environment variables:');
    for (const [key, errors] of Object.entries(result.error.flatten().fieldErrors)) {
      console.error(`  ${key}: ${errors?.join(', ')}`);
    }
    process.exit(1);
  }
  return result.data;
}

export const env = validateEnv();
export type Env = z.infer<typeof envSchema>;
