'use strict'

const DirectMessage = require('../models/DirectMessage')
const { query: queryDb } = require('../database/postgres')
const { sseSend, isOnline } = require('../services/sse')

/**
 * Extrai accountId e tenantId da request, compatível com:
 *   - verifyTeamToken  → req.teamAccount = { accountId, tenantId, ... }
 *   - verifyAnyToken   → req.admin = { id, tenant_id, ... } OU req.teamAccount
 */
function extractAuth(req) {
  const accountId = req.teamAccount?.accountId || req.admin?.id || null
  const tenantId  = req.tenantId || req.teamAccount?.tenantId || req.admin?.tenant_id || null
  return { accountId, tenantId }
}

class DirectMessageController {
  /**
   * POST /api/admin/inbox/direct-message
   * Enviar DM para um colaborador
   */
  async send(req, res) {
    try {
      const { to_account, content } = req.body
      const { accountId: fromAccountId, tenantId } = extractAuth(req)

      if (!fromAccountId || !tenantId) {
        return res.status(401).json({ error: 'Não autenticado' })
      }
      if (!to_account || !content?.trim()) {
        return res.status(400).json({ error: 'to_account e content obrigatórios' })
      }

      const msg = await DirectMessage.send(tenantId, fromAccountId, to_account, content)
      res.json(msg)

      // Notificar destinatário via SSE (se estiver conectado)
      sseSend(to_account, 'dm.new', {
        id:         msg.id,
        from:       fromAccountId,
        to:         to_account,
        content:    content,
        created_at: msg.created_at,
      })
    } catch (err) {
      console.error('[dm.send]', err.message)
      res.status(500).json({ error: 'Erro ao enviar mensagem' })
    }
  }

  /**
   * GET /api/admin/inbox/direct/:otherAccountId
   * Histórico de DMs com um colaborador
   */
  async getConversation(req, res) {
    try {
      const { otherAccountId } = req.params
      const { accountId, tenantId } = extractAuth(req)
      const limit = Math.min(Number(req.query.limit) || 50, 200)

      if (!accountId || !tenantId) {
        return res.status(401).json({ error: 'Não autenticado' })
      }
      if (!otherAccountId) {
        return res.status(400).json({ error: 'otherAccountId obrigatório' })
      }

      const msgs = await DirectMessage.getConversation(tenantId, accountId, Number(otherAccountId), limit)

      // Marcar como lidas ao abrir a conversa
      await DirectMessage.markAsRead(tenantId, accountId, Number(otherAccountId))

      res.json(msgs)
    } catch (err) {
      console.error('[dm.getConversation]', err.message)
      res.status(500).json({ error: 'Erro ao buscar conversa' })
    }
  }

  /**
   * GET /api/admin/inbox/direct-messages
   * Últimas DMs com cada colaborador + contagem de não lidas
   */
  async getLastMessages(req, res) {
    try {
      const { accountId, tenantId } = extractAuth(req)

      if (!accountId || !tenantId) {
        return res.status(401).json({ error: 'Não autenticado' })
      }

      const [lastMsgs, unreadByContact] = await Promise.all([
        DirectMessage.getLastMessagesByAccount(tenantId, accountId),
        DirectMessage.getUnreadCountByContact(tenantId, accountId),
      ])

      // Enriquecer com info do outro usuário + unread count
      const enriched = await Promise.all(
        lastMsgs.map(async (msg) => {
          const otherAccountId = msg.other_account
          const rows = await queryDb(
            `SELECT id, name, email, availability FROM accounts WHERE id = $1`,
            [otherAccountId]
          )
          const account = rows[0] || null

          return {
            id: msg.id,
            other_account: otherAccountId,
            other_account_name: account?.name || 'Unknown',
            other_account_availability: account?.availability || 'offline',
            last_message: msg.content,
            last_message_at: msg.created_at,
            unread_count: unreadByContact[otherAccountId] || 0,
          }
        })
      )

      res.json(enriched)
    } catch (err) {
      console.error('[dm.getLastMessages]', err.message)
      res.status(500).json({ error: 'Erro ao buscar DMs' })
    }
  }

  /**
   * GET /api/admin/inbox/colleagues
   * Listar todos os colaboradores do tenant com status online/offline
   * Para popular a coluna de contatos
   */
  async getColleagues(req, res) {
    try {
      const { accountId, tenantId } = extractAuth(req)

      if (!tenantId) {
        return res.status(401).json({ error: 'Não autenticado' })
      }

      // accountId pode ser null para admins sem account — nesse caso lista todos
      const colleagues = accountId
        ? await queryDb(
            `SELECT a.id, a.name, a.email, a.availability, a.avatar_url
             FROM accounts a
             WHERE a.tenant_id = $1
               AND a.id != $2
               AND a.active = true
             ORDER BY
               CASE WHEN a.availability = 'online' THEN 0
                    WHEN a.availability = 'busy' THEN 1
                    ELSE 2
               END,
               a.name`,
            [tenantId, accountId]
          )
        : await queryDb(
            `SELECT a.id, a.name, a.email, a.availability, a.avatar_url
             FROM accounts a
             WHERE a.tenant_id = $1
               AND a.active = true
             ORDER BY
               CASE WHEN a.availability = 'online' THEN 0
                    WHEN a.availability = 'busy' THEN 1
                    ELSE 2
               END,
               a.name`,
            [tenantId]
          )

      // Adicionar unread count para cada colega (só quando temos accountId)
      const unreadByContact = accountId
        ? await DirectMessage.getUnreadCountByContact(tenantId, accountId)
        : {}

      // Presença em tempo real: SSE conectado = online (exceto se DB diz busy)
      const enriched = colleagues.map(c => {
        let availability = c.availability
        if (isOnline(c.id)) {
          // Se conectado via SSE e não está como busy no DB → online
          if (availability !== 'busy') availability = 'online'
        } else {
          // Sem conexão SSE → offline independente do DB
          availability = 'offline'
        }
        return { ...c, availability, unread_count: unreadByContact[c.id] || 0 }
      })

      res.json(enriched)
    } catch (err) {
      console.error('[dm.getColleagues]', err.message)
      res.status(500).json({ error: 'Erro ao buscar colaboradores' })
    }
  }

  /**
   * PATCH /api/admin/inbox/direct/:messageId/read
   * Marcar uma DM como lida
   */
  async markAsRead(req, res) {
    try {
      const { messageId } = req.params
      const { accountId } = extractAuth(req)

      if (!accountId) {
        return res.status(401).json({ error: 'Não autenticado' })
      }

      // Verificar que a mensagem é para este usuário
      const rows = await queryDb(
        `SELECT id FROM direct_messages WHERE id = $1 AND to_account = $2`,
        [messageId, accountId]
      )
      const msg = rows[0] || null

      if (!msg) {
        return res.status(404).json({ error: 'Mensagem não encontrada' })
      }

      await queryDb(
        `UPDATE direct_messages SET read_at = NOW() WHERE id = $1`,
        [messageId]
      )

      res.json({ ok: true })
    } catch (err) {
      console.error('[dm.markAsRead]', err.message)
      res.status(500).json({ error: 'Erro ao marcar como lida' })
    }
  }
}

module.exports = new DirectMessageController()
