import { verifyToken } from '../utils/token.js'
import { SocketController } from '../controllers/socketController.js'
import { GeneralService } from '../share/generalservice.js'
import redis from '../utils/redis.js' // ใช้ Redis ที่มีเก็บ Session

export class SocketManager {
  constructor(io) {
    this.io = io
    this.generalService = new GeneralService()
    this.socketController = new SocketController()
  }

  initialize() {
    this.generalService.devhint(1, 'SocketManager.js', 'Initializing Socket.io')

    // Middleware: Authentication (เช็ค Token ก่อน Connect)
    this.io.use(async (socket, next) => {
      try {
        const token = socket.handshake.auth.token || socket.handshake.headers.token
        if (!token) return next(new Error('Authentication error'))
        
        const decoded = verifyToken(token)
        if (!decoded) return next(new Error('Invalid Token'))

        // เก็บข้อมูล User เข้า Socket Session
        socket.user = decoded
        socket.organization = decoded.organization // ใช้สำหรับ Schema
        next()
      } catch (err) {
        next(new Error('Authentication failed'))
      }
    })

    this.io.on('connection', async (socket) => {
      this.generalService.devhint(1, 'SocketManager.js', `User Connected: ${socket.user.usrnam}`)
      
      //  1. Save User Session to Redis (Pattern การเก็บ state)
      // key: "online:user_id", value: socket_id
      await redis.set(`online:${socket.user.id}`, socket.id)
      
      // Join Room ส่วนตัว (ตาม User ID)
      socket.join(socket.user.id.toString())

      // ==========================================
      //  Event Handlers (เรียก Controller Pattern)
      // ==========================================

      // 1. Send Notification (User ส่งหา User)
      socket.on('send_notification', async (data) => {
        await this.socketController.onSendNotification(this.io, socket, data)
      })

      // 2. VoIP: Call Request
      socket.on('call_user', async (data) => {
        await this.socketController.onCallUser(this.io, socket, data)
      })

      // 3. VoIP: Answer Call
      socket.on('answer_call', async (data) => {
        await this.socketController.onAnswerCall(this.io, socket, data)
      })

      // 4. VoIP: ICE Candidate (Network info)
      socket.on('ice_candidate', async (data) => {
        await this.socketController.onIceCandidate(this.io, socket, data)
      })
      
      // 5. VoIP: End Call
      socket.on('end_call', async (data) => {
        await this.socketController.onEndCall(this.io, socket, data)
      })

      // Disconnect
      socket.on('disconnect', async () => {
        this.generalService.devhint(1, 'SocketManager.js', `User Disconnected: ${socket.user.usrnam}`)
        await redis.del(`online:${socket.user.id}`)
      })
    })
  }
}