import { Prisma } from '@prisma/client'
import { prisma } from '../../infra/database/prisma'

export class ChatRepository {
  async findAllByInstance(tenantId: string, instanceId: string, opts: {
    limit?: number
    search?: string
    archived?: boolean
  } = {}) {
    const { limit = 200, search, archived = false } = opts

    return prisma.chat.findMany({
      where: {
        tenantId,
        instanceId,
        isArchived: archived,
        NOT: { OR: [
          { jid: { endsWith: '@lid' } },
          { jid: { contains: '@broadcast' } },
          { jid: { endsWith: '@newsletter' } },
        ]},
        ...(search
          ? {
              OR: [
                { jid: { contains: search, mode: 'insensitive' as const } },
                { contact: { name: { contains: search, mode: 'insensitive' as const } } },
                { contact: { notify: { contains: search, mode: 'insensitive' as const } } },
                { contact: { phone: { contains: search, mode: 'insensitive' as const } } },
              ],
            }
          : {}),
      },
      include: {
        contact: {
          select: {
            name: true,
            notify: true,
            verifiedName: true,
            phone: true,
            avatarUrl: true,
            scoreReputacao: true,
            flagRestricao: true,
          },
        },
        protocols: {
          where: { status: { in: ['OPEN', 'IN_PROGRESS', 'WAITING_CLIENT', 'WAITING_AGENT'] } },
          select: { number: true, status: true },
          take: 1,
          orderBy: { createdAt: 'desc' },
        },
        messages: {
          select: {
            body: true,
            fromMe: true,
            status: true,
            timestamp: true,
            type: true,
            pushName: true,
          },
          orderBy: { timestamp: 'desc' },
          take: 1,
        },
      },
      orderBy: [
        { isPinned: 'desc' },
        // COALESCE: usa lastMessageAt se existir, senão createdAt (chats novos sem msg)
        // Garante que chats recém-criados não caiam para o fundo da lista
        { lastMessageAt: { sort: 'desc', nulls: 'last' } },
        { createdAt: 'desc' },
      ],
      take: limit,
    })
  }

  async findById(id: string, tenantId: string) {
    return prisma.chat.findFirst({
      where: { id, tenantId },
      include: {
        contact: true,
        protocols: {
          where: { status: { in: ['OPEN', 'IN_PROGRESS', 'WAITING_CLIENT', 'WAITING_AGENT'] } },
          take: 1,
          orderBy: { createdAt: 'desc' },
        },
      },
    })
  }

  async findByJid(tenantId: string, instanceId: string, jid: string) {
    return prisma.chat.findUnique({
      where: { tenantId_instanceId_jid: { tenantId, instanceId, jid } },
      include: { contact: true },
    })
  }

  async clearUnread(id: string, tenantId: string) {
    return prisma.chat.updateMany({
      where: { id, tenantId },
      data: { unreadCount: 0 },
    })
  }

  async setArchived(id: string, tenantId: string, archived: boolean) {
    return prisma.chat.updateMany({
      where: { id, tenantId },
      data: { isArchived: archived },
    })
  }

  async setPinned(id: string, tenantId: string, pinned: boolean) {
    return prisma.chat.updateMany({
      where: { id, tenantId },
      data: { isPinned: pinned },
    })
  }

  async countUnreadByInstance(tenantId: string, instanceId: string): Promise<number> {
    const result = await prisma.chat.aggregate({
      where: { 
        tenantId, 
        instanceId, 
        isArchived: false,
        NOT: { OR: [
          { jid: { endsWith: '@lid' } },
          { jid: { contains: '@broadcast' } },
          { jid: { endsWith: '@newsletter' } },
        ]}
      },
      _sum: { unreadCount: true },
    })
    return result._sum.unreadCount ?? 0
  }
}
