import { prisma } from '../lib/prisma.js'
import { escapeHtml } from '../lib/escape-html.js'
import { getOtherUploadMaxFileBytes } from '../lib/upload-limits.js'
import { saveImageBufferToUploads } from '../lib/upload-images.js'

export async function registerUserPaymentRoutes(fastify) {
  fastify.post(
    '/api/me/orders/:id/pay',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      const order = await prisma.order.findFirst({ where: { id, userId } })
      if (!order) return reply.code(404).send({ error: 'Заказ не найден' })

      const paymentMethod = order.paymentMethod ?? 'online'
      if (paymentMethod === 'on_pickup') {
        return reply.code(409).send({ error: 'Для этого заказа оплата при получении — кнопка оплаты не нужна.' })
      }

      if (order.status === 'DELIVERY_FEE_ADJUSTMENT') {
        return reply
          .code(409)
          .send({
            error:
              'Оплата станет доступна после корректировки стоимости доставки администратором.',
          })
      }

      let nextStatus = order.status
      if (order.status === 'DRAFT') {
        await prisma.order.update({ where: { id }, data: { status: 'PENDING_PAYMENT' } })
        nextStatus = 'PENDING_PAYMENT'
        return { ok: true, status: nextStatus }
      }

      if (order.status === 'PAYMENT_VERIFICATION') {
        return { ok: true, status: nextStatus }
      }

      if (order.status === 'PENDING_PAYMENT') {
        if (!request.isMultipart()) {
          return reply
            .code(400)
            .send({ error: 'Отправьте multipart/form-data: поле detail и/или файл receipt' })
        }

        let detail = ''
        let receiptBuffer = null
        let receiptFilename = ''
        try {
          const otherLimit = getOtherUploadMaxFileBytes()
          const parts = request.parts({
            limits: {
              fileSize: otherLimit,
              files: 2,
            },
          })
          for await (const part of parts) {
            if (part.file) {
              if (part.fieldname === 'receipt') {
                if (receiptBuffer !== null) {
                  return reply.code(400).send({ error: 'Допускается один файл receipt' })
                }
                receiptBuffer = await part.toBuffer()
                receiptFilename = part.filename ?? 'receipt'
              }
            } else if (part.fieldname === 'detail') {
              detail = String(part.value ?? '').trim()
            }
          }
        } catch (err) {
          const msg = err instanceof Error ? err.message : 'Не удалось разобрать форму'
          return reply.code(400).send({ error: msg })
        }

        const hasDetail = detail.length > 0
        const hasReceipt = receiptBuffer !== null && receiptBuffer.length > 0

        if (!hasDetail && !hasReceipt) {
          return reply
            .code(400)
            .send({ error: 'Укажите текст о платеже и/или прикрепите изображение чека' })
        }

        const maxDetail = 2000
        if (detail.length > maxDetail) {
          return reply.code(400).send({ error: `Текст не длиннее ${maxDetail} символов` })
        }

        let attachmentUrl = null
        if (hasReceipt) {
          try {
            attachmentUrl = await saveImageBufferToUploads(receiptFilename, receiptBuffer)
          } catch (err) {
            const message = err instanceof Error ? err.message : 'Не удалось сохранить файл'
            const statusCode =
              err && typeof err === 'object' && 'statusCode' in err && Number.isInteger(err.statusCode)
                ? Number(err.statusCode)
                : 400
            return reply.code(statusCode).send({ error: message })
          }
        }

        const bodyHtml = hasDetail
          ? `<p>${escapeHtml(detail).replace(/\r\n|\n|\r/g, '<br/>')}</p>`
          : ''
        const messageText = `<p><strong>Подтверждение оплаты (перевод ВТБ / Сбербанк)</strong></p>${bodyHtml}`

        try {
          await prisma.$transaction(async (tx) => {
            await tx.order.update({ where: { id }, data: { status: 'PAYMENT_VERIFICATION' } })
            await tx.orderMessage.create({
              data: {
                orderId: id,
                authorType: 'user',
                text: messageText,
                attachmentUrl,
              },
            })
          })
        } catch (err) {
          return reply.code(500).send({ error: 'Не удалось сохранить оплату' })
        }

        return { ok: true, status: 'PAYMENT_VERIFICATION' }
      }

      return reply.code(409).send({ error: 'Сейчас нельзя выполнить оплату для этого заказа' })
    },
  )
}
