/**
 * config/assertProductionEnv.js
 *
 * Refuses to boot in production mode unless the operator has set
 * every secret / public-origin var the system depends on. Without
 * this guard, a missing PUBLIC_BASE_URL silently produces
 * `undefined/auth/verify?token=...` in verification emails.
 *
 * Also rejects placeholder / insecure values for SESSION_SECRET —
 * shipping the literal placeholder from .env.example would mean
 * every session cookie is forgeable.
 *
 * Called once at app startup (see app.js).
 */

'use strict';

// Known-bad placeholder values that must NEVER appear in production.
// These are the strings we ship in .env.example; if the operator
// forgot to replace them, fail loudly instead of booting.
const SESSION_SECRET_BAD_DEFAULTS = new Set([
  'change-this-to-a-long-random-string-min-64-chars',
  'change-me-in-env-min-64-chars',
  'changeme',
  'secret',
  'development',
]);

const REQUIRED = [
  { key: 'PUBLIC_BASE_URL',   why: 'Used in verification / password-reset / takedown email links' },
  { key: 'SESSION_SECRET',    why: 'Used to sign session cookies; default is INSECURE' },
  { key: 'TRUST_PROXY',       why: 'Required for Secure cookies + req.ip behind a reverse proxy' },
  // Fail-fast on placeholder Stripe + Resend keys. These are the most
  // common "I forgot to update .env" mistakes and they only fail at
  // the moment of the first call (a checkout, a verification email).
  // Catching them at boot gives the operator a clear message instead
  // of a 500 in /admin 12 hours after deploy.
  { key: 'STRIPE_SECRET_KEY', why: 'Required for any billing flow (checkout / portal / webhook verify)' },
  { key: 'STRIPE_WEBHOOK_SECRET', why: 'Required to verify Stripe webhook signatures (otherwise webhooks 400)' },
  { key: 'RESEND_API_KEY',    why: 'Required to send transactional email (verification, password reset, takedown letters)' },
];

// Placeholder patterns that mean "operator didn't replace the .env
// template". These are real-looking prefix matches but obviously fake.
const PLACEHOLDER_PATTERNS = [
  /_xxx$/i,                          // sk_live_xxx, price_xxx, etc.
  /^sk_test_dummy/i,
  /^pk_test_dummy/i,
  /^whsec_dummy/i,
  /^re_xxx$/i,
  /^change-this/i,
  /^your-key-here/i,
];

function assertProductionEnv() {
  if (process.env.NODE_ENV !== 'production') return;
  // Refuse to boot production with developer-only shims enabled.
  // These bypass real email/Scrape.do/MiniMax calls and would cause
  // takedown letters with 127.0.0.1 URLs to be sent to a real
  // recipient (or vice versa) — exactly the kind of embarrassing /
  // legally-bad mistake we MUST prevent.
  if (process.env.NCII_DEEP_DISCOVERY_TEST_MODE === '1' || process.env.NCII_ALERT_TEST_MODE === '1') {
    console.error('');
    console.error('========================================================================');
    console.error('  Shield — refusing to boot in production mode.');
    console.error('  NCII_DEEP_DISCOVERY_TEST_MODE and/or NCII_ALERT_TEST_MODE is set to 1.');
    console.error('  These are developer-only shims. They are unsafe in production');
    console.error('  (they will skip real Resend / Scrape.do / MiniMax calls and could');
    console.error('  ship test data to real recipients).');
    console.error('');
    console.error('  Unset them in .env or the cPanel env editor, then restart.');
    console.error('========================================================================');
    console.error('');
    process.exit(1);
  }
  const missing = REQUIRED.filter(r => !process.env[r.key] || !String(process.env[r.key]).trim());
  const errors = [...missing];

  // --- Placeholder-pattern check --------------------------------
  // Variables that ARE set but obviously still the template value
  // (e.g. STRIPE_SECRET_KEY=sk_live_xxx). These would boot, then
  // fail at the first Stripe / Resend call. Catch them now.
  for (const r of REQUIRED) {
    if (missing.find(m => m.key === r.key)) continue;   // already in missing
    const v = String(process.env[r.key] || '').trim();
    if (PLACEHOLDER_PATTERNS.some(p => p.test(v))) {
      errors.push({
        key: r.key,
        why: `is still the .env.example placeholder ("${v.length > 12 ? v.slice(0, 12) + '…' : v}"). Replace with a real value before deploying.`,
      });
    }
  }

  // --- SESSION_SECRET strength check ----------------------------
  const secret = process.env.SESSION_SECRET || '';
  if (secret) {
    if (secret.length < 32) {
      errors.push({
        key: 'SESSION_SECRET',
        why: `is too short (${secret.length} chars; minimum 32). Generate one with:  node -e "console.log(require('crypto').randomBytes(48).toString('base64'))"`,
      });
    } else if (SESSION_SECRET_BAD_DEFAULTS.has(secret)) {
      errors.push({
        key: 'SESSION_SECRET',
        why: 'is still the .env.example placeholder. Replace it with a random 48+ char string.',
      });
    } else if (/^[a-z]+$/i.test(secret) || /^(.)\1+$/.test(secret)) {
      // All letters, or all the same character repeated
      errors.push({
        key: 'SESSION_SECRET',
        why: 'appears to be too simple (low entropy). Use a random base64 / hex string.',
      });
    }
  }

  if (errors.length === 0) return;
  console.error('');
  console.error('========================================================================');
  console.error('  Shield — refusing to boot in production mode.');
  if (missing.length) {
    console.error('  The following environment variables are missing or empty:');
    console.error('');
    for (const e of missing) console.error(`  - ${e.key}: ${e.why}`);
  }
  if (errors.length > missing.length) {
    console.error('');
    console.error('  The following environment variables have invalid values:');
    console.error('');
    for (const e of errors.filter(x => !missing.includes(x))) {
      console.error(`  - ${e.key} ${e.why}`);
    }
  }
  console.error('');
  console.error('  Set them in .env or the cPanel "Setup Node.js App" environment editor,');
  console.error('  then restart the application.');
  console.error('========================================================================');
  console.error('');
  process.exit(1);
}

module.exports = { assertProductionEnv, REQUIRED, SESSION_SECRET_BAD_DEFAULTS };
