import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
  HOST: z.string().default('0.0.0.0'),
  PORT: z.string().default('3900').transform((value) => parseInt(value, 10)),

  DB_HOST: z.string(),
  DB_PORT: z.string().default('3306').transform((value) => parseInt(value, 10)),
  DB_USER: z.string(),
  DB_PASS: z.string(),
  DB_NAME: z.string(),

  REDIS_URL: z.string(),

  ENCRYPTION_MASTER_KEY: z
    .string()
    .length(64)
    .regex(/^[0-9a-fA-F]{64}$/, 'ENCRYPTION_MASTER_KEY must be 32 bytes hex-encoded (64 hex chars)'),

  LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
  ALLOWED_ORIGINS: z.string(),

  ADMIN_API_KEY: z.string().min(1).optional(),
  HMAC_SECRET: z.string().min(1).optional(),

  RATE_LIMIT_WINDOW_MS: z.string().default('900000').transform((value) => parseInt(value, 10)),
  RATE_LIMIT_MAX: z.string().default('100').transform((value) => parseInt(value, 10)),

  ONESIGNAL_APP_ID: z.string().min(1).optional(),
  ONESIGNAL_REST_API_KEY: z.string().min(1).optional(),

  PUBLIC_BASE_URL: z.string().url().optional(),
  IMAGES_DIR: z.string().default('public/images'),

  WEBSOCKET_ENABLED: z.enum(['true', 'false']).default('true'),
  WEBSOCKET_PATH: z.string().default('/ws'),

  COINMARKETCAP_API_BASE_URL: z.string().default('https://pro-api.coinmarketcap.com/v1'),
  COINMARKETCAP_API_KEYS: z
    .string()
    .min(1, 'COINMARKETCAP_API_KEYS is required')
    .transform((value) =>
      value
        .split(',')
        .map((key) => key.trim())
        .filter((key) => key.length > 0),
    )
    .refine((keys) => keys.length > 0, 'At least one CoinMarketCap API key is required'),
});

export type Env = z.infer<typeof envSchema> & {
  PUBLIC_BASE_URL: string;
};

const parseEnv = (): Env => {
  try {
    const parsed = envSchema.parse(process.env);
    return {
      ...parsed,
      PUBLIC_BASE_URL: parsed.PUBLIC_BASE_URL ?? `http://localhost:${parsed.PORT}`,
    };
  } catch (error) {
    if (error instanceof z.ZodError) {
      const issues = error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('\n');
      // eslint-disable-next-line no-console
      console.error(`Invalid environment configuration:\n${issues}`);
    } else {
      // eslint-disable-next-line no-console
      console.error('Unexpected error parsing environment variables', error);
    }
    process.exit(1);
  }
};

export const env = parseEnv();
