import { config as loadEnvironment } from 'dotenv';
import { z } from 'zod';

loadEnvironment({ quiet: true });

const booleanFromEnvironment = z
  .enum(['true', 'false'])
  .default('false')
  .transform((value) => value === 'true');

const enabledFromEnvironment = z
  .enum(['true', 'false'])
  .default('true')
  .transform((value) => value === 'true');

// ✅ A ligacao local (127.0.0.1) nunca precisa de TLS, por isso o binario
// true/false chegava. Uma base remota (ex: PostgreSQL num cPanel) tipicamente
// exige TLS mas com um certificado auto-assinado, que 'true' (exige CA
// publica) recusa sempre — por isso aceitam-se tambem 'require'/'no-verify'
// (mesmo vocabulario ja usado em scripts/migrate.ts), que activam TLS sem
// validar a cadeia de confianca.
const sslModeSchema = z.enum(['true', 'false', 'require', 'no-verify']);
export type SslMode = z.infer<typeof sslModeSchema>;
const sslModeFromEnvironment = sslModeSchema.default('false');

export function sslOptionFromMode(mode: SslMode): false | { rejectUnauthorized: boolean } {
  switch (mode) {
    case 'false':
      return false;
    case 'true':
      return { rejectUnauthorized: true };
    case 'require':
    case 'no-verify':
      return { rejectUnauthorized: false };
  }
}

const environmentSchema = z.object({
  NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
  BACKEND_HOST: z.string().trim().min(1).default('127.0.0.1'),
  BACKEND_PORT: z.coerce.number().int().min(1).max(65_535).default(3001),
  FRONTEND_ORIGIN: z.string().url().transform((value) => value.replace(/\/$/, '')),
  DATABASE_HOST: z.string().trim().min(1).default('127.0.0.1'),
  DATABASE_PORT: z.coerce.number().int().min(1).max(65_535).default(5432),
  DATABASE_NAME: z.string().trim().min(1).default('tonline_erp_local'),
  DATABASE_USER: z.string().trim().min(1).default('postgres'),
  DATABASE_PASSWORD: z.string().min(1, 'DATABASE_PASSWORD is required'),
  DATABASE_SSL: sslModeFromEnvironment,
  // ✅ Sincronizacao opcional para uma segunda base de dados (ex: cPanel),
  // usada por backend/src/repositories/kv-store.ts para replicar cada
  // escrita local. Todos os campos sao opcionais e independentes da ligacao
  // principal (DATABASE_*) - ausentes/vazios (ex: comentados no .env)
  // desliga a sincronizacao sem afectar o funcionamento local.
  SYNC_REMOTE_DATABASE_HOST: z.string().trim().optional(),
  SYNC_REMOTE_DATABASE_PORT: z.coerce.number().int().min(1).max(65_535).default(5432),
  SYNC_REMOTE_DATABASE_NAME: z.string().trim().optional(),
  SYNC_REMOTE_DATABASE_USER: z.string().trim().optional(),
  SYNC_REMOTE_DATABASE_PASSWORD: z.string().optional(),
  SYNC_REMOTE_DATABASE_SSL: sslModeFromEnvironment,
  SCHEDULER_ENABLED: enabledFromEnvironment,
  SCHEDULER_TIMEZONE: z.string().trim().min(1).default('Africa/Maputo'),
});

const parsedEnvironment = environmentSchema.safeParse(process.env);

if (!parsedEnvironment.success) {
  const variables = parsedEnvironment.error.issues
    .map((issue) => issue.path.join('.') || 'environment')
    .join(', ');

  throw new Error(`Invalid backend configuration: ${variables}`);
}

const environment = parsedEnvironment.data;

export const config = Object.freeze({
  nodeEnv: environment.NODE_ENV,
  host: environment.BACKEND_HOST,
  port: environment.BACKEND_PORT,
  frontendOrigin: environment.FRONTEND_ORIGIN,
  scheduler: Object.freeze({
    enabled: environment.SCHEDULER_ENABLED,
    timezone: environment.SCHEDULER_TIMEZONE,
  }),
  database: Object.freeze({
    host: environment.DATABASE_HOST,
    port: environment.DATABASE_PORT,
    name: environment.DATABASE_NAME,
    user: environment.DATABASE_USER,
    password: environment.DATABASE_PASSWORD,
    ssl: environment.DATABASE_SSL,
  }),
  // ✅ "enabled" so fica true quando host/nome/utilizador/password estao
  // todos preenchidos - basta apagar ou comentar qualquer um destes 4 no
  // .env para desligar a sincronizacao remota sem tocar em mais nada.
  syncRemote: Object.freeze({
    enabled: Boolean(
      environment.SYNC_REMOTE_DATABASE_HOST &&
      environment.SYNC_REMOTE_DATABASE_NAME &&
      environment.SYNC_REMOTE_DATABASE_USER &&
      environment.SYNC_REMOTE_DATABASE_PASSWORD,
    ),
    host: environment.SYNC_REMOTE_DATABASE_HOST || '',
    port: environment.SYNC_REMOTE_DATABASE_PORT,
    name: environment.SYNC_REMOTE_DATABASE_NAME || '',
    user: environment.SYNC_REMOTE_DATABASE_USER || '',
    password: environment.SYNC_REMOTE_DATABASE_PASSWORD || '',
    ssl: environment.SYNC_REMOTE_DATABASE_SSL,
  }),
});

export type AppConfig = typeof config;
