package fr.teamflash.fencerjudgeback.websocket.controllers

import fr.teamflash.fencerjudgeback.entities.PlayerBean
import fr.teamflash.fencerjudgeback.services.PlayerService
import fr.teamflash.fencerjudgeback.websocket.models.PlayerUpdateMessage
import org.springframework.context.event.EventListener
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.SendTo
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.socket.messaging.SessionSubscribeEvent

@Controller
@RequestMapping("/ws")
class PlayerWebSocketController(
    private val playerService: PlayerService,
    private val messagingTemplate: SimpMessagingTemplate
) {

    private val messageHistory = ArrayList<PlayerBean>()

    @MessageMapping("/player.update")
    @SendTo("/topic/player.updates")
    fun handlePlayerUpdate(playerUpdateMessage: PlayerUpdateMessage): PlayerUpdateMessage {
        // Create a PlayerBean from the update message
        val playerBean = PlayerBean(
            id = playerUpdateMessage.playerId,
            name = playerUpdateMessage.name,
            firstName = playerUpdateMessage.firstName,
            club = playerUpdateMessage.club
        )
        
        // Update the player in the database
        playerService.updatePlayer(playerBean.id ?: 0, playerBean)
        
        // Return the update message to be broadcast to all subscribers
        return playerUpdateMessage
    }
    
    /**
     * Broadcast a player update to all connected clients
     * This method can be called from other services
     */
    fun broadcastPlayerUpdate(playerBean: PlayerBean, type: PlayerUpdateMessage.UpdateType = PlayerUpdateMessage.UpdateType.PLAYER_UPDATE) {
        val updateMessage = PlayerUpdateMessage.fromPlayerBean(playerBean, type)
        messagingTemplate.convertAndSend("/topic/player.updates", updateMessage)
    }

    @EventListener
    fun handleWebSocketSubscribeListener(event: SessionSubscribeEvent) {
        val headerAccessor = StompHeaderAccessor.wrap(event.message)
        if ("/topic/player.updates" == headerAccessor.destination) {
            // When a client subscribes, send them the current players
            val players = playerService.getAll()
            players.forEach { player ->
                messagingTemplate.convertAndSend(
                    "/topic/player.updates", 
                    PlayerUpdateMessage.fromPlayerBean(player, PlayerUpdateMessage.UpdateType.PLAYER_UPDATE)
                )
            }
        }
    }

    @MessageMapping
    fun addPlayerToMainList(playerBean: PlayerBean) {
        playerService.addPlayer(playerBean)
        broadcastPlayerUpdate(playerBean, PlayerUpdateMessage.UpdateType.PLAYER_CREATE)
    }
}