const express = require('express')
const socketio = require('socket.io')
const http = require('http')
const cors = require('cors')
const { addUser, removeUser, getUser, getUsersInRoom } = require('./users')
const path = require('path')

const PORT = process.env.PORT || 5000

const app = express()
const server = http.createServer(app)
const io = socketio(server, {
    cors: {
        origin: "*",
        methods: ["GET", "POST"]
    }
})

app.use(cors())

// Store latest game states by room code for bot API access
const gameStates = new Map()

// HTTP endpoint for bot to get game state
app.get('/api/game/:roomCode/state', (req, res) => {
    const roomCode = req.params.roomCode
    const state = gameStates.get(roomCode)
    
    if (state) {
        res.json({
            success: true,
            gameState: state,
            timestamp: new Date().toISOString()
        })
    } else {
        res.status(404).json({
            success: false,
            error: 'Game room not found or no state available'
        })
    }
})

// HTTP endpoint for bot to submit action
app.post('/api/game/:roomCode/action', express.json(), (req, res) => {
    const roomCode = req.params.roomCode
    const action = req.body
    
    // minimal log for incoming bot action
    console.log(`[Bot HTTP Action] Room: ${roomCode}`)
    
    // Emit action to the game room via socket
    io.to(roomCode).emit('botActionReceived', action)
    
    res.json({
        success: true,
        message: 'Action received and forwarded to game'
    })
})

io.on('connection', socket => {
    socket.on('join', (payload, callback) => {
        let numberOfUsersInRoom = getUsersInRoom(payload.room).length

        const { error, newUser} = addUser({
            id: socket.id,
            name: numberOfUsersInRoom===0 ? 'Player 1' : 'Player 2',
            room: payload.room
        })

        if(error)
            return callback(error)

        socket.join(newUser.room)

        io.to(newUser.room).emit('roomData', {room: newUser.room, users: getUsersInRoom(newUser.room)})
        socket.emit('currentUserData', {name: newUser.name})
        callback()
    })

    socket.on('initGameState', gameState => {
        const user = getUser(socket.id)
        if(user)
            io.to(user.room).emit('initGameState', gameState)
    })

    socket.on('updateGameState', gameState => {
        const user = getUser(socket.id)
        if(user) {
            io.to(user.room).emit('updateGameState', gameState)
            
            // Also update stored game state for bot REST API access
            const currentState = gameStates.get(user.room) || {}
            gameStates.set(user.room, {
                ...currentState,
                ...gameState,
                room: user.room,
                lastUpdate: new Date().toISOString()
            })
        }
    })

    socket.on('sendMessage', (payload, callback) => {
        const user = getUser(socket.id)
        io.to(user.room).emit('message', {user: user.name, text: payload.message})
        callback()
    })

    // Bot integration: receive game state from Player 2 (bot)
    socket.on('botGameState', gameState => {
        const user = getUser(socket.id)
        if(user && user.name === 'Player 2') {
            // Store latest game state for bot access (do not log full JSON to avoid noise)
            gameStates.set(user.room, {
                ...gameState,
                room: user.room,
                lastUpdate: new Date().toISOString()
            })
        }
    })

    // Bot integration: receive bot action (play card or draw)
    socket.on('botAction', (action, callback) => {
        const user = getUser(socket.id)
        if(user && user.name === 'Player 2') {
            // Forward action to game logic. Client will handle via regular game state updates
            callback && callback({ success: true })
        }
    })

    // Bot integration: request current game state
    socket.on('requestGameState', (callback) => {
        const user = getUser(socket.id)
        if(user) {
            // Request game state from room
            socket.to(user.room).emit('gameStateRequested')
            callback && callback({ success: true })
        }
    })

    socket.on('disconnect', () => {
        const user = removeUser(socket.id)
        if(user)
            io.to(user.room).emit('roomData', {room: user.room, users: getUsersInRoom(user.room)})
    })
})

//serve static assets in production
if(process.env.NODE_ENV === 'production') {
	//set static folder
	app.use(express.static('client/build'))
	app.get('*', (req, res) => {
		res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
	})
}

server.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`)
})