import { createInitialState, punteggio, servizio, setVinti } from './gameState.js'

export function createWsMixin(role) {
    return {
        data() {
            return {
                ws: null,
                wsConnected: false,
                isConnecting: false,
                reconnectTimeout: null,
                reconnectAttempts: 0,
                maxReconnectDelay: 30000,
                state: createInitialState(),
            }
        },
        computed: {
            punt()     { return punteggio(this.state.sp.striscia) },
            servHome() { return servizio(this.state.sp.striscia) },
            set()      { return setVinti(this.state.sp.striscia) },
        },
        mounted() {
            this.connectWebSocket()
            if (import.meta.hot) {
                import.meta.hot.on('vite:beforeUpdate', () => {
                    if (this.reconnectTimeout) {
                        clearTimeout(this.reconnectTimeout)
                        this.reconnectTimeout = null
                    }
                })
            }
        },
        beforeUnmount() {
            if (this.reconnectTimeout) {
                clearTimeout(this.reconnectTimeout)
                this.reconnectTimeout = null
            }
            if (this.ws) {
                this.ws.onclose = null
                this.ws.onerror = null
                this.ws.onmessage = null
                this.ws.onopen = null
                try {
                    if (this.ws.readyState === WebSocket.OPEN) {
                        this.ws.close(1000, 'Component unmounting')
                    } else if (this.ws.readyState === WebSocket.CONNECTING) {
                        this.ws.close()
                    }
                } catch (err) {
                    console.error(`[${role}] Error closing WebSocket:`, err)
                }
                this.ws = null
            }
        },
        methods: {
            connectWebSocket() {
                if (this.isConnecting) return
                if (this.ws) {
                    this.ws.onclose = null
                    this.ws.onerror = null
                    this.ws.onmessage = null
                    this.ws.onopen = null
                    try {
                        if (this.ws.readyState === WebSocket.OPEN) {
                            this.ws.close(1000, 'Reconnecting')
                        } else if (this.ws.readyState === WebSocket.CONNECTING) {
                            this.ws.close()
                        }
                    } catch (err) {
                        console.error(`[${role}] Error closing previous WebSocket:`, err)
                    }
                    this.ws = null
                }

                this.isConnecting = true
                const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'
                const params = new URLSearchParams(location.search)
                const defaultHost = (location.hostname === 'localhost' || location.hostname === '::1')
                    ? `127.0.0.1${location.port ? `:${location.port}` : ''}`
                    : location.host
                const wsUrl = `${protocol}//${params.get('wsHost') || defaultHost}/ws`

                try {
                    this.ws = new WebSocket(wsUrl)
                } catch (err) {
                    console.error(`[${role}] Failed to create WebSocket:`, err)
                    this.isConnecting = false
                    this.scheduleReconnect()
                    return
                }

                this.ws.onopen = () => {
                    this.isConnecting = false
                    this.wsConnected = true
                    this.reconnectAttempts = 0
                    try {
                        this.ws?.send(JSON.stringify({ type: 'register', role }))
                    } catch (err) {
                        console.error(`[${role}] Failed to register:`, err)
                    }
                }

                this.ws.onmessage = (event) => {
                    try {
                        const msg = JSON.parse(event.data)
                        if (msg.type === 'state') this.state = msg.state
                        else this.onWsMessage?.(msg)
                    } catch (e) {
                        console.error(`[${role}] Error parsing message:`, e)
                    }
                }

                this.ws.onclose = (event) => {
                    this.isConnecting = false
                    this.wsConnected = false
                    if (event.code !== 1000 && event.code !== 1001) this.scheduleReconnect()
                }

                this.ws.onerror = () => {
                    this.isConnecting = false
                    this.wsConnected = false
                }
            },

            scheduleReconnect() {
                if (this.reconnectTimeout) return
                const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay)
                this.reconnectAttempts++
                this.reconnectTimeout = setTimeout(() => {
                    this.reconnectTimeout = null
                    this.connectWebSocket()
                }, delay)
            },

            sendWs(msg) {
                if (!this.wsConnected || this.ws?.readyState !== WebSocket.OPEN) return false
                try {
                    this.ws.send(JSON.stringify(msg))
                    return true
                } catch (err) {
                    console.error(`[${role}] Failed to send:`, err)
                    return false
                }
            },
        },
    }
}
