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

export async function registerUserMessageRoutes(fastify) {
  fastify.get(
    '/api/me/orders/:id/messages',
    { 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 items = await prisma.orderMessage.findMany({ where: { orderId: id }, orderBy: { createdAt: 'asc' } })
      return { items }
    },
  )

  fastify.post(
    '/api/me/orders/:id/messages',
    { 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 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 } })
      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 readStates = await prisma.userOrderMessageReadState.findMany({ where: { userId } })
      const lastReadByOrder = new Map(readStates.map((r) => [r.orderId, r.lastReadAt]))

      let count = 0
      for (const o of orders) {
        const lastRead = lastReadByOrder.get(o.id) ?? new Date(0)
        const n = await prisma.orderMessage.count({
          where: { orderId: o.id, authorType: 'admin', createdAt: { gt: lastRead } },
        })
        count += n
      }
      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 items = []
      for (const o of orders) {
        const lastMsg = o.messages[0]
        if (!lastMsg) continue
        const lastRead = lastReadByOrder.get(o.id) ?? new Date(0)
        const unreadCount = await prisma.orderMessage.count({
          where: { orderId: o.id, authorType: 'admin', createdAt: { gt: lastRead } },
        })
        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,
        })
      }
      return { items }
    },
  )

  fastify.post(
    '/api/me/orders/:id/messages/read',
    { 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 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 }
    },
  )
}
