/**
 * Step-handlers для platform-smtp.
 *
 * SMTP-настройки платформы (SuperAdmin). Безопасность: пароль хранится
 * зашифрованным (DataProtection) и НИКОГДА не отдаётся клиентом — только флаг
 * hasSmtpPassword. Изменение требует осмысленную причину (≥10) для журнала.
 * В конце возвращаем настройки в чистое состояние, чтобы не ломать
 * forgot-password в других сценариях.
 */
import { login, makeClient } from '../lib/api.js'
import { psql } from '../lib/db.js'
import type { CheckResult, Step, Report } from '../lib/report.js'

interface Ctx { apiOnly: boolean; sa?: string }
interface StepCtx { ctx: Ctx; step: Step; report: Report }

function check(step: Step, c: CheckResult) { step.checks.push(c) }
function q1(sql: string): string { return (psql(sql).trim().split('\n')[0] ?? '').trim() }
const PLAINTEXT = 'SuperSecret123pwd'

async function ensureSa(ctx: Ctx) {
  if (!ctx.sa) ctx.sa = (await login('admin@food-market.local', 'Admin12345!')).accessToken
  return makeClient(ctx.sa)
}

export async function step01_clean_state({ ctx, step }: StepCtx) {
  const api = await ensureSa(ctx)
  const r = await api.put('/api/super-admin/platform-settings', {
    reason: 'Сброс SMTP для e2e-теста', smtpHost: null, smtpPort: null, smtpUseSsl: false,
    smtpStartTls: false, smtpUsername: null, newSmtpPassword: '__clear__', fromEmail: null, fromName: null,
  })
  check(step, { kind: 'api', description: 'PUT очистки → 204', ok: r.status === 204, detail: `status=${r.status}` })
  const get = await api.get('/api/super-admin/platform-settings')
  check(step, { kind: 'api', description: 'hasSmtpPassword=false после очистки', ok: get.data?.hasSmtpPassword === false, detail: `has=${get.data?.hasSmtpPassword}` })
}

export async function step02_reason_required({ ctx, step }: StepCtx) {
  const api = await ensureSa(ctx)
  const empty = await api.put('/api/super-admin/platform-settings', { reason: '', smtpHost: 'smtp.example.com' })
  check(step, { kind: 'api', description: 'PUT без причины → 400', ok: empty.status === 400, detail: `status=${empty.status}` })
  const short = await api.put('/api/super-admin/platform-settings', { reason: 'коротко', smtpHost: 'smtp.example.com' })
  check(step, { kind: 'api', description: 'PUT причина <10 → 400', ok: short.status === 400, detail: `status=${short.status}` })
}

export async function step03_test_send_not_configured({ ctx, step }: StepCtx) {
  const api = await ensureSa(ctx)
  const r = await api.post('/api/super-admin/platform-settings/test-send', { toEmail: 'nobody@example.kz' })
  check(step, { kind: 'api', description: 'test-send без настроенного SMTP → 400', ok: r.status === 400, detail: `status=${r.status}` })
}

export async function step04_save_smtp({ ctx, step }: StepCtx) {
  const api = await ensureSa(ctx)
  const r = await api.put('/api/super-admin/platform-settings', {
    reason: 'Настройка SMTP-сервера для рассылок', smtpHost: 'smtp.example.com', smtpPort: 587,
    smtpUseSsl: false, smtpStartTls: true, smtpUsername: 'mailer@example.com',
    newSmtpPassword: PLAINTEXT, fromEmail: 'no-reply@example.com', fromName: 'Food Market',
  })
  check(step, { kind: 'api', description: 'PUT валидной конфигурации → 204', ok: r.status === 204, detail: `status=${r.status}` })
  const get = await api.get('/api/super-admin/platform-settings')
  check(step, { kind: 'api', description: 'hasSmtpPassword=true', ok: get.data?.hasSmtpPassword === true, detail: `has=${get.data?.hasSmtpPassword}` })
  check(step, { kind: 'api', description: 'smtpHost/username сохранены и возвращаются',
    ok: get.data?.smtpHost === 'smtp.example.com' && get.data?.smtpUsername === 'mailer@example.com',
    detail: `host=${get.data?.smtpHost}` })
}

export async function step05_password_encrypted({ ctx, step, report }: StepCtx) {
  const api = await ensureSa(ctx)
  const get = await api.get('/api/super-admin/platform-settings')
  const raw = JSON.stringify(get.data ?? {})
  check(step, { kind: 'api', description: 'Ответ GET не содержит пароль в открытом виде',
    ok: !raw.includes(PLAINTEXT), detail: raw.includes(PLAINTEXT) ? 'НАЙДЕН ПЛЕЙНТЕКСТ' : 'ok' })
  if (raw.includes(PLAINTEXT)) report.bug({ step: '05', severity: 'critical', title: 'SMTP-пароль возвращается клиенту в открытом виде', detail: '' })
  const enc = q1(`SELECT "SmtpPasswordEncrypted" FROM platform_settings LIMIT 1`)
  check(step, { kind: 'db', description: 'В БД пароль не плейнтекст и не пуст',
    ok: !!enc && enc !== PLAINTEXT, detail: enc === PLAINTEXT ? 'ПЛЕЙНТЕКСТ В БД' : `len=${enc.length}` })
  if (enc === PLAINTEXT) report.bug({ step: '05', severity: 'critical', title: 'SMTP-пароль хранится в БД в открытом виде', detail: '' })
}

export async function step06_clear_password({ ctx, step }: StepCtx) {
  const api = await ensureSa(ctx)
  const r = await api.put('/api/super-admin/platform-settings', {
    reason: 'Очистка пароля и сброс хоста после теста', smtpHost: null, smtpPort: null,
    smtpUseSsl: false, smtpStartTls: false, smtpUsername: null, newSmtpPassword: '__clear__', fromEmail: null, fromName: null,
  })
  check(step, { kind: 'api', description: 'PUT __clear__ → 204', ok: r.status === 204, detail: `status=${r.status}` })
  const get = await api.get('/api/super-admin/platform-settings')
  check(step, { kind: 'api', description: 'hasSmtpPassword=false', ok: get.data?.hasSmtpPassword === false, detail: `has=${get.data?.hasSmtpPassword}` })
}
