import { randomUUID } from 'crypto'
import { getSession } from '@/lib/session'
import { getGameCharacters } from '@/lib/characters'
import { createCheckoutSession } from '@/lib/stripe'
import { createSumUpCheckout, sumupConfigured } from '@/lib/sumup'
import { getPaidService, fulfillOk } from '@/lib/paid-services'
import { payServiceWithDPoints } from '@/lib/pay-with-dpoints'

/** Locale seguro (es/en) para construir la URL de retorno. */
function safeLocale(v: unknown): string {
  return v === 'en' ? 'en' : 'es'
}

export async function POST(request: Request, { params }: { params: Promise<{ service: string }> }) {
  const { service } = await params
  const cfg = getPaidService(service)
  if (!cfg) return Response.json({ success: false, error: 'invalidService' }, { status: 404 })

  const session = await getSession()
  if (!session.accountId) return Response.json({ success: false, error: 'notAuthenticated' }, { status: 401 })

  let body: Record<string, string> = {}
  try {
    body = await request.json()
  } catch {
    return Response.json({ success: false, error: 'invalidRequest' }, { status: 400 })
  }
  const character = String(body.character ?? '')
  if (!character) return Response.json({ success: false, error: 'invalidCharacter' })

  const chars = await getGameCharacters(session.accountId)
  if (!chars.find((c) => c.name === character)) {
    return Response.json({ success: false, error: 'invalidCharacter' })
  }

  // Comprobación previa al pago (condiciones del servicio, p.ej. cambio de facción / transferencia).
  if (cfg.precheck) {
    const pc = await cfg.precheck({ accountId: session.accountId, email: session.bnetEmail || '', character, body })
    if (!pc.ok) return Response.json({ success: false, error: 'ineligible', message: pc.message })
  }

  // Campos extra del servicio (gold_amount, destination_account...) -> metadata.
  // `service` va en metadata para que el webhook sepa qué entregar sin la URL.
  const metadata: Record<string, string> = { service }
  for (const f of cfg.extraFields) {
    const v = String(body[f] ?? '').trim()
    if (!v) return Response.json({ success: false, error: 'missingFields' })
    metadata[f] = v
  }

  const price = await cfg.price(metadata)
  if (!price || price <= 0) return Response.json({ success: false, error: 'invalidRequest' })

  const site = process.env.SITE_URL || ''
  const ip = (request.headers.get('x-forwarded-for') || '').split(',')[0].trim() || '0.0.0.0'
  const productName = cfg.productName(character, metadata)

  // Pago con saldo PD: se descuenta el saldo y se ejecuta la acción al momento
  // (sin pasarela). Devuelve la URL de éxito para que el form redirija igual que
  // con Stripe/SumUp; la entrega ya se ha realizado aquí.
  if (String(body.provider) === 'pd') {
    const r = await payServiceWithDPoints(session.accountId, price, () => cfg.fulfill(character, metadata).then(fulfillOk))
    if (!r.success) return Response.json({ success: false, error: r.error })
    const locale = safeLocale(body.locale)
    return Response.json({
      success: true,
      url: `${site}/${locale}/service-success?service=${service}&provider=pd&name=${encodeURIComponent(character)}`,
    })
  }

  // Pago por SumUp (euros): al pagar, la reconciliación/return ejecuta la acción
  // del servicio sobre el personaje (no acredita PD).
  if (String(body.provider) === 'sumup') {
    if (!sumupConfigured()) return Response.json({ success: false, error: 'notConfigured' })
    const reference = randomUUID()
    const r = await createSumUpCheckout({
      accountId: session.accountId,
      username: session.username || '',
      email: session.bnetEmail || '',
      acoreIp: ip,
      amount: price,
      points: 0,
      reference,
      description: productName,
      returnUrl: `${site}/service-success?service=${service}&provider=sumup&ref=${reference}`,
      service,
      characterName: character,
      metadata,
    })
    if (!r.success || !r.url) return Response.json({ success: false, error: r.error || 'sumupError' })
    return Response.json({ success: true, url: r.url })
  }

  const r = await createCheckoutSession({
    accountId: session.accountId,
    username: session.username || '',
    email: session.bnetEmail || '',
    acoreIp: ip,
    amount: price,
    characterName: character,
    productName,
    successUrl: `${site}/service-success?service=${service}`,
    cancelUrl: `${site}/${service}`,
    metadata,
  })
  if (!r.success || !r.url) return Response.json({ success: false, error: 'stripeError' })
  return Response.json({ success: true, url: r.url })
}
