import { issueEmailCode, normalizeEmail, verifyEmailCode } from '../lib/auth.js'
import { prisma } from '../lib/prisma.js'

function mapUserForClient(user) {
  const adminEmail = normalizeEmail(process.env.ADMIN_EMAIL)
  const userEmail = normalizeEmail(user.email)
  return {
    id: user.id,
    email: user.email,
    name: user.name,
    phone: user.phone,
    isAdmin: Boolean(adminEmail) && userEmail === adminEmail,
  }
}

export async function registerAuthRoutes(fastify) {
  fastify.post('/api/auth/request-code', async (request, reply) => {
    const email = normalizeEmail(request.body?.email)
    if (!email || !email.includes('@')) return reply.code(400).send({ error: 'Некорректная почта' })

    await issueEmailCode({ email, purpose: 'login' })
    return { ok: true }
  })

  fastify.post('/api/auth/verify-code', async (request, reply) => {
    const email = normalizeEmail(request.body?.email)
    const code = String(request.body?.code || '').trim()
    if (!email || !email.includes('@')) return reply.code(400).send({ error: 'Некорректная почта' })
    if (!code || code.length !== 6) return reply.code(400).send({ error: 'Код должен быть из 6 цифр' })

    const ok = await verifyEmailCode({ email, purpose: 'login', code })
    if (!ok) return reply.code(401).send({ error: 'Неверный или истёкший код' })

    const user = await prisma.user.upsert({
      where: { email },
      update: {},
      create: { email },
    })

    const token = fastify.jwt.sign({ sub: user.id, email: user.email })
    return { token, user: mapUserForClient(user) }
  })

  fastify.get(
    '/api/me',
    { preHandler: [fastify.authenticate] },
    async (request) => {
      const userId = request.user.sub
      const user = await prisma.user.findUnique({ where: { id: userId } })
      if (!user) return { user: null }
      return { user: mapUserForClient(user) }
    },
  )

  fastify.post(
    '/api/me/change-email/request-code',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const newEmail = normalizeEmail(request.body?.newEmail)
      if (!newEmail || !newEmail.includes('@')) return reply.code(400).send({ error: 'Некорректная почта' })

      const exists = await prisma.user.findUnique({ where: { email: newEmail } })
      if (exists) return reply.code(409).send({ error: 'Эта почта уже занята' })

      await issueEmailCode({ email: newEmail, purpose: 'change_email', userId })
      return { ok: true }
    },
  )

  fastify.post(
    '/api/me/change-email/verify',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const newEmail = normalizeEmail(request.body?.newEmail)
      const code = String(request.body?.code || '').trim()
      if (!newEmail || !newEmail.includes('@')) return reply.code(400).send({ error: 'Некорректная почта' })
      if (!code || code.length !== 6) return reply.code(400).send({ error: 'Код должен быть из 6 цифр' })

      const exists = await prisma.user.findUnique({ where: { email: newEmail } })
      if (exists) return reply.code(409).send({ error: 'Эта почта уже занята' })

      const ok = await verifyEmailCode({ email: newEmail, purpose: 'change_email', code, userId })
      if (!ok) return reply.code(401).send({ error: 'Неверный или истёкший код' })

      const user = await prisma.user.update({
        where: { id: userId },
        data: { email: newEmail },
      })
      return { user: mapUserForClient(user) }
    },
  )

  fastify.patch(
    '/api/me/profile',
    { preHandler: [fastify.authenticate] },
    async (request, reply) => {
      const userId = request.user.sub
      const nameRaw = request.body?.name
      const name = nameRaw === null || nameRaw === undefined ? null : String(nameRaw).trim()
      const phoneRaw = request.body?.phone
      const phone = phoneRaw === null || phoneRaw === undefined ? null : String(phoneRaw).trim()

      if (name !== null && name.length > 40) return reply.code(400).send({ error: 'Имя/ник максимум 40 символов' })
      if (phone !== null) {
        const compact = phone.replace(/[\s()-]/g, '')
        if (compact.length > 20) return reply.code(400).send({ error: 'Телефон слишком длинный' })
        if (compact.length && !/^\+?\d{7,20}$/.test(compact)) {
          return reply.code(400).send({ error: 'Некорректный телефон' })
        }
      }

      const updated = await prisma.user.update({
        where: { id: userId },
        data: { name: name && name.length ? name : null, phone: phone && phone.length ? phone : null },
      })
      return { user: mapUserForClient(updated) }
    },
  )
}
