import { prisma } from '../lib/prisma.js'

function normalizePhoneLite(input) {
  const s = String(input || '').trim()
  if (!s) return ''
  return s.replace(/[\s()-]/g, '')
}

function validateAddressPayload(body, reply) {
  const labelRaw = body?.label
  const label = labelRaw === null || labelRaw === undefined ? null : String(labelRaw).trim()
  if (label !== null && label.length > 40) return reply.code(400).send({ error: 'Метка адреса максимум 40 символов' })

  const recipientName = String(body?.recipientName || '').trim()
  if (!recipientName) return reply.code(400).send({ error: 'Укажите ФИО получателя' })
  if (recipientName.length > 80) return reply.code(400).send({ error: 'ФИО получателя максимум 80 символов' })

  const recipientPhone = normalizePhoneLite(body?.recipientPhone)
  if (!recipientPhone) return reply.code(400).send({ error: 'Укажите телефон получателя' })
  if (!/^\+?\d{7,20}$/.test(recipientPhone)) return reply.code(400).send({ error: 'Некорректный телефон получателя' })

  const addressLine = String(body?.addressLine || '').trim()
  if (!addressLine) return reply.code(400).send({ error: 'Укажите адрес' })
  if (addressLine.length > 200) return reply.code(400).send({ error: 'Адрес максимум 200 символов' })

  const commentRaw = body?.comment
  const comment = commentRaw === null || commentRaw === undefined ? null : String(commentRaw).trim()
  if (comment !== null && comment.length > 200) return reply.code(400).send({ error: 'Комментарий максимум 200 символов' })

  const lat = Number(body?.lat)
  const lng = Number(body?.lng)
  if (!Number.isFinite(lat) || lat < -90 || lat > 90) return reply.code(400).send({ error: 'Некорректная широта' })
  if (!Number.isFinite(lng) || lng < -180 || lng > 180) return reply.code(400).send({ error: 'Некорректная долгота' })

  return {
    label,
    recipientName,
    recipientPhone,
    addressLine,
    comment,
    lat,
    lng,
  }
}

export async function registerUserAddressRoutes(fastify) {
  fastify.get(
    '/api/me/addresses',
    { preHandler: [fastify.authenticate] },
    async (request) => {
      const userId = request.user.sub
      const items = await prisma.shippingAddress.findMany({
        where: { userId },
        orderBy: [{ isDefault: 'desc' }, { updatedAt: 'desc' }],
      })
      return { items }
    },
  )

  fastify.post(
    '/api/me/addresses',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const validated = validateAddressPayload(request.body, reply)
      if (!validated) return

      const isDefault = Boolean(request.body?.isDefault)
      const created = await prisma.$transaction(async (tx) => {
        if (isDefault) {
          await tx.shippingAddress.updateMany({ where: { userId, isDefault: true }, data: { isDefault: false } })
        }
        return tx.shippingAddress.create({
          data: {
            userId,
            ...validated,
            isDefault,
          },
        })
      })
      return reply.code(201).send({ item: created })
    },
  )

  fastify.patch(
    '/api/me/addresses/:id',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } })
      if (!existing) return reply.code(404).send({ error: 'Адрес не найден' })

      const body = request.body ?? {}
      const data = {}

      if (body.label !== undefined) {
        const labelRaw = body.label
        const label = labelRaw === null || labelRaw === undefined ? null : String(labelRaw).trim()
        if (label !== null && label.length > 40) return reply.code(400).send({ error: 'Метка адреса максимум 40 символов' })
        data.label = label && label.length ? label : null
      }

      if (body.recipientName !== undefined) {
        const v = String(body.recipientName || '').trim()
        if (!v) return reply.code(400).send({ error: 'Укажите ФИО получателя' })
        if (v.length > 80) return reply.code(400).send({ error: 'ФИО получателя максимум 80 символов' })
        data.recipientName = v
      }

      if (body.recipientPhone !== undefined) {
        const v = normalizePhoneLite(body.recipientPhone)
        if (!v) return reply.code(400).send({ error: 'Укажите телефон получателя' })
        if (!/^\+?\d{7,20}$/.test(v)) return reply.code(400).send({ error: 'Некорректный телефон получателя' })
        data.recipientPhone = v
      }

      if (body.addressLine !== undefined) {
        const v = String(body.addressLine || '').trim()
        if (!v) return reply.code(400).send({ error: 'Укажите адрес' })
        if (v.length > 200) return reply.code(400).send({ error: 'Адрес максимум 200 символов' })
        data.addressLine = v
      }

      if (body.comment !== undefined) {
        const commentRaw = body.comment
        const comment = commentRaw === null || commentRaw === undefined ? null : String(commentRaw).trim()
        if (comment !== null && comment.length > 200) return reply.code(400).send({ error: 'Комментарий максимум 200 символов' })
        data.comment = comment && comment.length ? comment : null
      }

      if (body.lat !== undefined) {
        const lat = Number(body.lat)
        if (!Number.isFinite(lat) || lat < -90 || lat > 90) return reply.code(400).send({ error: 'Некорректная широта' })
        data.lat = lat
      }

      if (body.lng !== undefined) {
        const lng = Number(body.lng)
        if (!Number.isFinite(lng) || lng < -180 || lng > 180) return reply.code(400).send({ error: 'Некорректная долгота' })
        data.lng = lng
      }

      const setDefault = body.isDefault === true
      const updated = await prisma.$transaction(async (tx) => {
        if (setDefault) {
          await tx.shippingAddress.updateMany({ where: { userId, isDefault: true }, data: { isDefault: false } })
        }
        return tx.shippingAddress.update({
          where: { id },
          data: {
            ...data,
            ...(setDefault ? { isDefault: true } : {}),
          },
        })
      })

      return { item: updated }
    },
  )

  fastify.delete(
    '/api/me/addresses/:id',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } })
      if (!existing) return reply.code(404).send({ error: 'Адрес не найден' })

      await prisma.shippingAddress.delete({ where: { id } })
      return reply.code(204).send()
    },
  )

  fastify.post(
    '/api/me/addresses/:id/default',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      const existing = await prisma.shippingAddress.findFirst({ where: { id, userId } })
      if (!existing) return reply.code(404).send({ error: 'Адрес не найден' })

      const updated = await prisma.$transaction(async (tx) => {
        await tx.shippingAddress.updateMany({ where: { userId, isDefault: true }, data: { isDefault: false } })
        return tx.shippingAddress.update({ where: { id }, data: { isDefault: true } })
      })

      return { item: updated }
    },
  )
}
