package fr.teamflash.fencerjudgeback.websocket.controllers

import fr.teamflash.fencerjudgeback.config.CHANNEL_MATCH_NAME
import fr.teamflash.fencerjudgeback.entities.MatchBean
import fr.teamflash.fencerjudgeback.entities.MatchUpdateBean
import fr.teamflash.fencerjudgeback.services.MatchService
import fr.teamflash.fencerjudgeback.websocket.models.MatchUpdateMessage
import org.springframework.context.event.EventListener
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
import org.springframework.stereotype.Controller
import org.springframework.web.socket.messaging.SessionSubscribeEvent

@Controller
class MatchWebSocketController(
    private val matchService: MatchService,
    private val messagingTemplate: SimpMessagingTemplate
) {

    private var mainId:Long? = 1
    private val messageHistory = ArrayList<MatchBean>()

    @MessageMapping("/all")
    fun receiveMessage(message: MatchBean) {
        println("/ws/matches $message")
        messageHistory.add(message)

        // Envoyer la liste des messages sur le channel
        //Si la variable est dans le même package il faut enlever WebSocketConfig.
        messagingTemplate.convertAndSend(CHANNEL_MATCH_NAME, messageHistory)
    }

    /**
     * Handle match update requests from clients
     * Client sends to: /app/match.update
     * Server broadcasts to: /topic/match.updates
     */
    @MessageMapping("/update")
    fun handleMatchUpdate(matchUpdateMessage: MatchUpdateMessage): MatchUpdateMessage {
        // Create a MatchBean from the update message
        val matchBean = MatchBean(
            id = matchUpdateMessage.matchId,
            player1ID = matchUpdateMessage.player1Id,
            player2ID = matchUpdateMessage.player2Id,
            refereeID = matchUpdateMessage.refereeId,
            score1 = matchUpdateMessage.score1,
            score2 = matchUpdateMessage.score2,
            date = matchUpdateMessage.date
        )
        
        // Update the match in the database
        matchService.updateMatch(matchBean.id, matchBean)
        
        // Return the update message to be broadcast to all subscribers
        return matchUpdateMessage
    }
    
    /**
     * Broadcast a match update to all connected clients
     * This method can be called from other services
     */
    fun broadcastMatchUpdate(matchBean: MatchBean, type: MatchUpdateMessage.UpdateType = MatchUpdateMessage.UpdateType.SCORE_UPDATE) {
        val updateMessage = MatchUpdateMessage.fromMatchBean(matchBean, type)
        messagingTemplate.convertAndSend("/topic/match.updates", updateMessage)
    }

    //A mettre dans le controller
    @EventListener
    fun handleWebSocketSubscribeListener(event: SessionSubscribeEvent) {
        val headerAccessor = StompHeaderAccessor.wrap(event.message)
        if (CHANNEL_MATCH_NAME == headerAccessor.destination) {
            messagingTemplate.convertAndSend(CHANNEL_MATCH_NAME, messageHistory)
            println("Lancement du WebSocket")
        }
    }

    @MessageMapping("/plusPoint")
    fun addPoint(matchUpdateBean: MatchUpdateBean) {
        val playerId = matchUpdateBean.playerId
        val match = matchUpdateBean.match
        print("plus")
        if (match != null) {
            print("minus")
            when (playerId) {
                match.player1ID -> if (match.score1 > 0) match.score1 -= 1
                match.player2ID -> if (match.score2 > 0) match.score2 -= 1
            }
            matchService.updateMatch(match.id, match)
            broadcastMatchUpdate(match)
        }
    }

        @MessageMapping("/minusPoint")
        fun minusPoint(matchUpdateBean: MatchUpdateBean) {
            val playerId = matchUpdateBean.playerId
            val match = matchUpdateBean.match
            print("minus")
            if (match != null) {
                when (playerId) {
                    match.player1ID -> if (match.score1 > 0) match.score1 -= 1
                    match.player2ID -> if (match.score2 > 0) match.score2 -= 1
                }
                matchService.updateMatch(match.id, match)
                broadcastMatchUpdate(match)
            }
        }

    @MessageMapping("/add")
    fun addMatchtoMainList(match:MatchBean) {
        match.id = mainId;
        matchService.addMatch(match)
        messageHistory.add(match)
        broadcastMatchUpdate(match, MatchUpdateMessage.UpdateType.NEW_MATCH)
        mainId = mainId?.plus(1)
        println("Ajout du match $match.id en bdd")
    }
}