/**
 * Stage Swagger: проверяет что OpenAPI генерируется и все новые модули
 * присутствуют. Stage работает в Production, поэтому Swagger там
 * выключен — этот сценарий гоняется ЛОКАЛЬНО (E2E_ADMIN_URL=http://localhost:5081).
 * Если эндпоинт недоступен, шаги помечаются skip.
 */
import { makeClient } from '../lib/api.js'
import type { CheckResult, Step, Report } from '../lib/report.js'

type Ctx = {
  apiOnly: boolean
  swagger?: { paths: Record<string, unknown>; components?: { schemas?: Record<string, unknown> } }
}
interface StepCtx { ctx: Ctx; step: Step; report: Report }

function check(step: Step, c: CheckResult) { step.checks.push(c) }

export async function sw01_swagger_endpoint({ ctx, step, report }: StepCtx) {
  const api = makeClient()
  const r = await api.get('/swagger/v1/swagger.json')
  if (r.status === 404) {
    step.status = 'skip'
    step.notes.push('Swagger не доступен на этом окружении (видимо Production). Запусти локально с E2E_ADMIN_URL=http://localhost:5081.')
    return
  }
  check(step, { kind: 'api', description: 'GET /swagger/v1/swagger.json → 200', ok: r.status === 200, detail: `${r.status}` })
  check(step, { kind: 'api', description: 'paths.length > 50', ok: typeof r.data === 'object' && r.data && Object.keys(r.data.paths ?? {}).length > 50, detail: `paths=${Object.keys(r.data?.paths ?? {}).length}` })
  ctx.swagger = r.data
}

export async function sw02_all_new_modules_present({ ctx, step, report }: StepCtx) {
  if (!ctx.swagger) { step.status = 'skip'; return }
  const paths = Object.keys(ctx.swagger.paths ?? {})
  const expected = [
    '/api/inventory/enters', '/api/inventory/losses', '/api/inventory/transfers',
    '/api/inventory/inventories', '/api/inventory/stock',
    '/api/purchases/supplier-returns', '/api/purchases/supplies',
    '/api/sales/demands', '/api/sales/retail',
    '/api/reports/sales', '/api/reports/stock', '/api/reports/profit', '/api/reports/abc',
    '/api/admin/audit-log', '/api/me/2fa/enroll', '/api/me/2fa/verify',
    '/api/me/2fa/disable', '/api/pos/v1', '/api/auth/signup',
  ]
  const missing = expected.filter(e => !paths.some(p => p.startsWith(e)))
  check(step, {
    kind: 'api', description: `Все ${expected.length} новых модулей присутствуют`,
    ok: missing.length === 0, detail: missing.length ? `missing: ${missing.join(', ')}` : 'все ок',
  })
}

export async function sw03_schema_ids_unique({ ctx, step, report }: StepCtx) {
  if (!ctx.swagger) { step.status = 'skip'; return }
  const schemas = ctx.swagger.components?.schemas ?? {}
  const names = Object.keys(schemas)
  // Уже проверка факта генерации (если был бы collision, swagger.json не сгенерился).
  // Дополнительно — нет дублей по lowercase (защита от case-insensitive дубля).
  const lower = new Map<string, string[]>()
  for (const n of names) {
    const k = n.toLowerCase()
    const arr = lower.get(k) ?? []
    arr.push(n)
    lower.set(k, arr)
  }
  const dups = [...lower.entries()].filter(([, v]) => v.length > 1)
  check(step, {
    kind: 'api', description: `schemaId дубликатов нет (всего ${names.length})`,
    ok: dups.length === 0, detail: dups.length ? `dups: ${dups.map(([k]) => k).slice(0, 5).join(', ')}` : 'unique',
  })
}
