import { z } from "zod";

/**
 * Configuração da aplicação a partir do ambiente (.env).
 *
 * O `.env` é carregado pelo próprio Node 24 via a flag `--env-file=.env`
 * (recurso nativo) — NÃO usamos `dotenv`. Os scripts em package.json já
 * passam essa flag.
 *
 * Validação com zod: falha cedo, com mensagem clara, se algo essencial
 * faltar ou estiver malformado. NUNCA imprimimos o valor de segredos
 * (regra não-negociável do CLAUDE.md) — só o nome da variável.
 */

const schema = z.object({
  // Chave mestra de criptografia (AES-256-GCM): 32 bytes em hex (64 chars).
  MASTER_KEY: z
    .string()
    .regex(
      /^[0-9a-fA-F]{64}$/,
      "MASTER_KEY deve ser hex de 64 caracteres (32 bytes). Gere com: node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"",
    ),

  // MySQL
  DB_HOST: z.string().min(1, "DB_HOST é obrigatório"),
  DB_PORT: z.coerce.number().int().positive().default(3306),
  DB_USER: z.string().min(1, "DB_USER é obrigatório"),
  DB_PASSWORD: z.string().default(""),
  DB_NAME: z.string().min(1, "DB_NAME é obrigatório"),

  // Redis
  REDIS_URL: z.string().min(1, "REDIS_URL é obrigatório"),

  // API
  PORT: z.coerce.number().int().positive().default(3000),
  // Interface de escuta. Atrás de proxy reverso (subdomínio+SSL) use
  // 127.0.0.1 para não expor a porta diretamente.
  HOST: z.string().default("0.0.0.0"),
  // Segredo para assinar os JWT de sessão do painel (>= 32 chars).
  JWT_SECRET: z
    .string()
    .min(32, "JWT_SECRET deve ter ao menos 32 caracteres"),
  // Janela de validade do token de sessão.
  JWT_EXPIRES_IN: z.string().default("12h"),

  // Workers
  PRICING_INTERVAL_MS: z.coerce.number().int().positive().default(60000),
  /**
   * Quando "false" (padrão), o pricing roda em DRY-RUN: calcula e registra em
   * price_adjustments SEM aplicar na exchange. Ligue só após conferir.
   */
  PRICING_APPLY: z
    .string()
    .default("false")
    .transform((v) => v === "1" || v.toLowerCase() === "true"),
  CHAT_POLL_INTERVAL_MS: z.coerce.number().int().positive().default(15000),
  SYNC_INTERVAL_MS: z.coerce.number().int().positive().default(120000),
  NODE_ENV: z
    .enum(["development", "production", "test"])
    .default("development"),
});

export type Env = z.infer<typeof schema>;

function loadEnv(): Env {
  const parsed = schema.safeParse(process.env);
  if (!parsed.success) {
    // Só o caminho/issue de cada campo — nunca o valor recebido.
    const issues = parsed.error.issues
      .map((i) => `  - ${i.path.join(".") || "(raiz)"}: ${i.message}`)
      .join("\n");
    throw new Error(
      `Configuração de ambiente inválida. Confira o seu .env:\n${issues}`,
    );
  }
  return Object.freeze(parsed.data);
}

export const env: Env = loadEnv();
