import { NOTIFICATION_EVENTS } from '../../../shared/constants/notification-events.js'
import { asyncHandler } from '../lib/async-handler.js'
import { findUserOrder } from '../lib/find-user-order.js'
import { prisma } from '../lib/prisma.js'

export async function registerUserMessageRoutes(fastify) {
  fastify.get(
    '/api/me/orders/:id/messages',
    { preHandler: [fastify.authenticate] },
    asyncHandler(async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      await findUserOrder(prisma, id, userId)
      const items = await prisma.orderMessage.findMany({
        where: { orderId: id },
        orderBy: { createdAt: 'asc' },
      })
      return { items }
    }),
  )

  fastify.post(
    '/api/me/orders/:id/messages',
    { preHandler: [fastify.authenticate] },
    asyncHandler(async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      await findUserOrder(prisma, id, userId)
      const text = String(request.body?.text || '').trim()
      if (!text) return reply.code(400).send({ error: 'Сообщение пустое' })
      if (text.length > 2000) return reply.code(400).send({ error: 'Сообщение слишком длинное' })
      const msg = await prisma.orderMessage.create({
        data: { orderId: id, authorType: 'user', text },
      })

      request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_MESSAGE_SENT, {
        orderId: id,
        authorType: 'user',
        messageId: msg.id,
        preview: text,
      })

      return reply.code(201).send({ item: msg })
    }),
  )

  fastify.get('/api/me/messages/unread-count', { preHandler: [fastify.authenticate] }, async (request) => {
    const userId = request.user.sub
    const orders = await prisma.order.findMany({
      where: { userId },
      select: { id: true },
    })
    if (orders.length === 0) return { count: 0 }

    const orderIds = orders.map((o) => o.id)
    const readStates = await prisma.userOrderMessageReadState.findMany({
      where: { userId },
    })
    const lastReadByOrder = new Map(readStates.map((r) => [r.orderId, r.lastReadAt]))

    const adminMessages = await prisma.orderMessage.findMany({
      where: { orderId: { in: orderIds }, authorType: 'admin' },
      select: { orderId: true, createdAt: true },
    })

    let count = 0
    for (const msg of adminMessages) {
      const lastRead = lastReadByOrder.get(msg.orderId) ?? new Date(0)
      if (msg.createdAt > lastRead) count++
    }
    return { count }
  })

  fastify.get('/api/me/conversations', { preHandler: [fastify.authenticate] }, async (request) => {
    const userId = request.user.sub
    const orders = await prisma.order.findMany({
      where: { userId, messages: { some: {} } },
      select: {
        id: true,
        status: true,
        deliveryType: true,
        messages: {
          orderBy: { createdAt: 'desc' },
          take: 1,
          select: { text: true, createdAt: true },
        },
      },
      orderBy: { updatedAt: 'desc' },
    })

    const readStates = await prisma.userOrderMessageReadState.findMany({
      where: { userId },
    })
    const lastReadByOrder = new Map(readStates.map((r) => [r.orderId, r.lastReadAt]))

    const orderIds = orders.map((o) => o.id)
    const unreadCounts = new Map()
    if (orderIds.length > 0) {
      const adminMessages = await prisma.orderMessage.findMany({
        where: { orderId: { in: orderIds }, authorType: 'admin' },
        select: { orderId: true, createdAt: true },
      })
      for (const msg of adminMessages) {
        const lastRead = lastReadByOrder.get(msg.orderId) ?? new Date(0)
        if (msg.createdAt > lastRead) {
          unreadCounts.set(msg.orderId, (unreadCounts.get(msg.orderId) ?? 0) + 1)
        }
      }
    }

    const items = []
    for (const o of orders) {
      const lastMsg = o.messages[0]
      if (!lastMsg) continue
      items.push({
        orderId: o.id,
        status: o.status,
        deliveryType: o.deliveryType,
        lastMessageAt: lastMsg.createdAt,
        preview: lastMsg.text.length > 280 ? `${lastMsg.text.slice(0, 277)}…` : lastMsg.text,
        unreadCount: unreadCounts.get(o.id) ?? 0,
      })
    }
    return { items }
  })

  fastify.post(
    '/api/me/orders/:id/messages/read',
    { preHandler: [fastify.authenticate] },
    asyncHandler(async (request, reply) => {
      const userId = request.user.sub
      const { id } = request.params
      await findUserOrder(prisma, id, userId)

      const now = new Date()
      await prisma.userOrderMessageReadState.upsert({
        where: { userId_orderId: { userId, orderId: id } },
        create: { userId, orderId: id, lastReadAt: now },
        update: { lastReadAt: now },
      })
      return { ok: true }
    }),
  )
}
