import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'

const envPath = resolve(process.argv[2] || '.env.production')
const raw = readFileSync(envPath, 'utf8')

function parseEnv(text) {
  const env = {}
  for (const line of text.split(/\r?\n/)) {
    const trimmed = line.trim()
    if (!trimmed || trimmed.startsWith('#')) continue
    const match = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/)
    if (!match) continue
    const [, key, rest] = match
    let value = rest.trim()
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
      value = value.slice(1, -1)
    }
    env[key] = value
  }
  return env
}

const env = parseEnv(raw)
const failures = []
const warnings = []

function isPlaceholder(value) {
  const text = String(value || '').trim()
  if (!text) return true
  return /replace-with|change-me|changeme|your-|example\.com|example_/i.test(text)
}

function report(symbol, key, status) {
  console.log(`${symbol} ${key}: ${status}`)
}

function requireSet(key) {
  if (isPlaceholder(env[key])) {
    failures.push(`${key} 为空或仍是占位值`)
    report('✗', key, 'empty-or-placeholder')
    return false
  }
  report('✓', key, 'set')
  return true
}

function requireExact(key, expected) {
  if (String(env[key] || '') !== expected) {
    failures.push(`${key} 必须为 ${expected}`)
    report('✗', key, `expected-${expected}`)
    return false
  }
  report('✓', key, expected)
  return true
}

function requireAny(label, keys) {
  const hit = keys.find((key) => !isPlaceholder(env[key]))
  if (!hit) {
    failures.push(`${label} 缺少：${keys.join(' 或 ')}`)
    report('✗', label, 'empty-or-placeholder')
    return false
  }
  report('✓', label, `set:${hit}`)
  return true
}

function warnIfEmpty(key, message) {
  if (isPlaceholder(env[key])) {
    warnings.push(message)
    report('·', key, 'empty-optional')
  } else {
    report('✓', key, 'set')
  }
}

function requireEmpty(key) {
  if (String(env[key] || '').trim()) {
    failures.push(`${key} 生产环境必须为空`)
    report('✗', key, 'must-be-empty')
    return false
  }
  report('✓', key, 'empty')
  return true
}

function parseByteSize(value) {
  const text = String(value || '').trim()
  const match = text.match(/^(\d+(?:\.\d+)?)\s*(b|kb|kib|mb|mib|gb|gib)?$/i)
  if (!match) return 0
  const amount = Number(match[1])
  const unit = (match[2] || 'b').toLowerCase()
  const multiplier = {
    b: 1,
    kb: 1024,
    kib: 1024,
    mb: 1024 * 1024,
    mib: 1024 * 1024,
    gb: 1024 * 1024 * 1024,
    gib: 1024 * 1024 * 1024,
  }[unit] || 1
  return amount * multiplier
}

console.log(`生产环境审计：${envPath}`)

requireExact('NODE_ENV', 'production')
requireSet('PUBLIC_DOMAIN')
requireSet('FRONTEND_ORIGIN')
requireSet('WEB_ORIGIN')
requireSet('CORS_ALLOW_ORIGINS')
requireSet('NEXT_PUBLIC_API_BASE_URL')
requireAny('api_internal_url', ['API_INTERNAL_URL', 'SERVER_API_BASE_URL'])

requireExact('ENABLE_DEV_AUTH_CODE', 'false')
requireExact('ENABLE_DEV_ADMIN_TOKEN', 'false')
requireExact('ENABLE_DEV_PAYMENT', 'false')
requireEmpty('ADMIN_TOKEN')
requireEmpty('NEXT_PUBLIC_ADMIN_TOKEN')

requireSet('JWT_SECRET')
requireSet('POSTGRES_PASSWORD')
requireSet('BOOTSTRAP_SUPER_ADMIN_PHONE')

requireSet('ALIBABA_CLOUD_ACCESS_KEY_ID')
requireSet('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
requireSet('ALIBABA_CLOUD_SMS_SIGN_NAME')
requireSet('ALIBABA_CLOUD_SMS_TEMPLATE_CODE')

requireSet('WECHAT_MINIAPP_APP_ID')
requireSet('WECHAT_MINIAPP_APP_SECRET')

if (String(env.WECHAT_PAY_ENABLED || '').toLowerCase() === 'true') {
  requireSet('WECHAT_PAY_MCH_ID')
  requireSet('WECHAT_PAY_APP_ID')
  requireSet('WECHAT_PAY_API_V3_KEY')
  requireSet('WECHAT_PAY_MCH_SERIAL_NO')
  requireAny('wechat_pay_private_key', ['WECHAT_PAY_PRIVATE_KEY_PATH', 'WECHAT_PAY_PRIVATE_KEY_BASE64'])
  requireSet('WECHAT_PAY_PUBLIC_KEY_ID')
  requireAny('wechat_pay_platform_key', ['WECHAT_PAY_PUBLIC_KEY_PATH', 'WECHAT_PAY_PUBLIC_KEY_BASE64'])
  requireSet('WECHAT_PAY_NOTIFY_URL')
}

requireExact('OBJECT_STORAGE_DRIVER', 's3')
requireSet('S3_ENDPOINT')
requireSet('S3_PUBLIC_ENDPOINT')
requireSet('S3_ACCESS_KEY_ID')
requireSet('S3_SECRET_ACCESS_KEY')
requireSet('S3_BUCKET_PUBLIC')
requireSet('S3_BUCKET_PRIVATE')

const rawUploadMaxBytes = Number(env.RAW_UPLOAD_MAX_BYTES || 0)
if (rawUploadMaxBytes < 1024 * 1024 * 1024) {
  failures.push('RAW_UPLOAD_MAX_BYTES 必须至少为 1073741824')
  report('✗', 'RAW_UPLOAD_MAX_BYTES', 'too-small-or-empty')
} else {
  report('✓', 'RAW_UPLOAD_MAX_BYTES', 'set')
}

const maxUploadSizeBytes = parseByteSize(env.MAX_UPLOAD_SIZE)
if (maxUploadSizeBytes < 1024 * 1024 * 1024) {
  failures.push('MAX_UPLOAD_SIZE 必须至少为 1024MB，避免 Caddy 先于后端拒绝大文件')
  report('✗', 'MAX_UPLOAD_SIZE', 'too-small-or-empty')
} else {
  report('✓', 'MAX_UPLOAD_SIZE', 'set')
}

warnIfEmpty('METRICS_TOKEN', 'METRICS_TOKEN 未设置；公网已由 Caddy 阻断，内网 metrics 暂不启用 bearer token。')
warnIfEmpty('SENTRY_DSN', 'SENTRY_DSN 未设置；上线后错误聚合能力会受限。')
requireSet('ALERTMANAGER_TOKEN')
requireSet('GRAFANA_ADMIN_PASSWORD')

if (warnings.length) {
  console.log('\nWarnings:')
  for (const warning of warnings) console.log(`- ${warning}`)
}

if (failures.length) {
  console.error('\nFailures:')
  for (const failure of failures) console.error(`- ${failure}`)
  process.exit(1)
}

console.log('\n生产环境审计通过：未输出任何密钥值。')
