import { Server as SocketIOServer } from 'socket.io'
import type { Server as HttpServer } from 'http'
import jwt from 'jsonwebtoken'
import { env } from '../../config/env'
import { logger } from '../../config/logger'
import { dragonfly } from '../cache/dragonfly'

// TTL em segundos: 70 = 2× o heartbeat do frontend (30s) + margem
const PRESENCE_TTL = 70

interface SocketUser {
  sub: string    // userId / tenantId (matches JWT payload)
  role: string
}

export function buildSocketServer(httpServer: HttpServer): SocketIOServer {
  const io = new SocketIOServer(httpServer, {
    cors: {
      origin: env.FRONTEND_URL,
      credentials: true,
    },
    transports: ['websocket', 'polling'],
  })

  // Autenticação por token JWT no handshake
  io.use((socket, next) => {
    const token = socket.handshake.auth?.token as string | undefined
    if (!token) {
      next(new Error('Token não fornecido'))
      return
    }
    try {
      const payload = jwt.verify(token, env.JWT_SECRET) as SocketUser
      socket.data.userId = payload.sub
      socket.data.role = payload.role
      next()
    } catch {
      next(new Error('Token inválido'))
    }
  })

  io.on('connection', (socket) => {
    const userId: string = socket.data.userId
    logger.debug({ userId, socketId: socket.id }, 'Socket conectado')

    // Cliente entra na sala do seu tenant automaticamente
    socket.join(`tenant:${userId}`)

    // Registra presença do usuário no Dragonfly com TTL
    dragonfly.set(`presence:user:${userId}`, socket.id, PRESENCE_TTL).catch(() => {})

    // Cliente pode entrar em salas específicas de instância ou chat
    socket.on('join:instance', (instanceId: string) => {
      socket.join(`instance:${instanceId}`)
    })

    socket.on('join:chat', (chatId: string) => {
      socket.join(`chat:${chatId}`)
    })

    socket.on('leave:chat', (chatId: string) => {
      socket.leave(`chat:${chatId}`)
    })

    // Heartbeat do frontend a cada 30s — renova TTL de presença
    socket.on('user:heartbeat', () => {
      dragonfly.set(`presence:user:${userId}`, socket.id, PRESENCE_TTL).catch(() => {})
    })

    socket.on('disconnect', (reason) => {
      logger.debug({ userId, reason }, 'Socket desconectado')
      // Remove presença imediatamente ao desconectar
      dragonfly.del(`presence:user:${userId}`).catch(() => {})
    })
  })

  return io
}
