/**
 * Smoke-test da infra base (passo 1 do roadmap).
 *
 * Prova as 4 peças: config, criptografia, MySQL e Redis. As duas primeiras
 * rodam offline (sem rede); MySQL e Redis dependem de o servidor estar
 * acessível — valide no host4. Sai com código != 0 se qualquer etapa falhar.
 *
 * Uso: npm run smoke:infra   (carrega o .env via --env-file)
 */

import { env } from "../src/config/env.js";
import { encrypt, decrypt, lastFour } from "../src/crypto/secretbox.js";
import { ping, closePool } from "../src/db/mysql.js";
import { pingRedis, closeRedis } from "../src/redis/redis.js";

let failures = 0;

function ok(label: string, detail = ""): void {
  console.log(`✅ ${label}${detail ? ` — ${detail}` : ""}`);
}
function fail(label: string, err: unknown): void {
  failures++;
  const msg = err instanceof Error ? err.message : String(err);
  console.error(`❌ ${label} — ${msg}`);
}

// 1. Config -----------------------------------------------------------------
try {
  // Importar `env` já valida o schema. Confirmamos só o tamanho da chave,
  // NUNCA o valor.
  const keyBytes = Buffer.from(env.MASTER_KEY, "hex").length;
  if (keyBytes !== 32) throw new Error(`MASTER_KEY tem ${keyBytes} bytes (esperado 32).`);
  ok("config", `NODE_ENV=${env.NODE_ENV}, DB=${env.DB_NAME}@${env.DB_HOST}:${env.DB_PORT}, MASTER_KEY=32 bytes`);
} catch (err) {
  fail("config", err);
}

// 2. Criptografia (round-trip + detecção de adulteração) --------------------
try {
  const plaintext = "teste-123";
  const box = encrypt(plaintext);
  const back = decrypt(box);
  if (back !== plaintext) throw new Error("round-trip não bateu.");

  // Adulterar 1 byte do ciphertext deve fazer o decrypt lançar.
  const tampered = Buffer.from(box);
  tampered[tampered.length - 1] ^= 0xff;
  let detected = false;
  try {
    decrypt(tampered);
  } catch {
    detected = true;
  }
  if (!detected) throw new Error("adulteração NÃO foi detectada pela authTag.");

  ok("crypto", `round-trip OK, buffer=${box.length} bytes, adulteração detectada, mask=${lastFour("sk_live_ABCD3F9A")}`);
} catch (err) {
  fail("crypto", err);
}

// 3. MySQL ------------------------------------------------------------------
try {
  await ping();
  ok("mysql", "SELECT 1 OK");
} catch (err) {
  fail("mysql", err);
} finally {
  try {
    await closePool();
  } catch {
    /* ignore */
  }
}

// 4. Redis ------------------------------------------------------------------
try {
  await pingRedis();
  ok("redis", "PING → PONG");
} catch (err) {
  fail("redis", err);
} finally {
  try {
    await closeRedis();
  } catch {
    /* ignore */
  }
}

// Resultado -----------------------------------------------------------------
if (failures > 0) {
  console.error(`\n${failures} etapa(s) falharam.`);
  process.exit(1);
}
console.log("\nTodas as etapas passaram.");
process.exit(0);
