package com.example.godeye.network

import android.util.Log
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import okhttp3.*
import org.json.JSONObject
import java.util.concurrent.TimeUnit

/**
 * WebSocket клиент для подключения к серверу сигналинга
 */
class SignalingClient {

    companion object {
        private const val TAG = "SignalingClient"
        private const val DEFAULT_SERVER_URL = "ws://192.168.219.108:3001" // Замените на IP вашего компьютера
        private const val RECONNECT_DELAY = 5000L // 5 секунд
    }

    private var webSocket: WebSocket? = null
    private var client: OkHttpClient? = null
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    // Состояние подключения
    private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED)
    val connectionState: StateFlow<ConnectionState> = _connectionState.asStateFlow()

    // ID текущего клиента и сессии
    private var clientId: String? = null
    private var sessionId: String? = null

    // Callback для обработки сообщений
    var onMessageReceived: ((JSONObject) -> Unit)? = null
    var onSessionCreated: ((String) -> Unit)? = null
    var onOperatorJoined: (() -> Unit)? = null

    enum class ConnectionState {
        DISCONNECTED,
        CONNECTING,
        CONNECTED,
        ERROR
    }

    /**
     * Подключение к серверу сигналинга
     */
    fun connect(serverUrl: String = DEFAULT_SERVER_URL) {
        if (_connectionState.value == ConnectionState.CONNECTING ||
            _connectionState.value == ConnectionState.CONNECTED) {
            Log.w(TAG, "Уже подключен или подключается")
            return
        }

        Log.i(TAG, "🔗 Подключение к серверу сигналинга: $serverUrl")
        _connectionState.value = ConnectionState.CONNECTING

        try {
            client = OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(0, TimeUnit.MILLISECONDS) // Бесконечное время ожидания для WebSocket
                .build()

            val request = Request.Builder()
                .url(serverUrl)
                .build()

            webSocket = client?.newWebSocket(request, object : WebSocketListener() {
                override fun onOpen(webSocket: WebSocket, response: Response) {
                    Log.i(TAG, "✅ WebSocket подключен")
                    _connectionState.value = ConnectionState.CONNECTED
                }

                override fun onMessage(webSocket: WebSocket, text: String) {
                    Log.d(TAG, "📨 Получено сообщение: $text")
                    handleMessage(text)
                }

                override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                    Log.i(TAG, "🔌 WebSocket закрыт: $code - $reason")
                    _connectionState.value = ConnectionState.DISCONNECTED
                    scheduleReconnect()
                }

                override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                    Log.e(TAG, "❌ Ошибка WebSocket: ${t.message}", t)
                    _connectionState.value = ConnectionState.ERROR
                    scheduleReconnect()
                }
            })

        } catch (e: Exception) {
            Log.e(TAG, "❌ Ошибка создания WebSocket: ${e.message}", e)
            _connectionState.value = ConnectionState.ERROR
        }
    }

    /**
     * Отключение от сервера
     */
    fun disconnect() {
        Log.i(TAG, "🔌 Отключение от сервера сигналинга")

        scope.coroutineContext.cancelChildren()
        webSocket?.close(1000, "Пользователь отключился")
        webSocket = null
        client = null
        clientId = null
        sessionId = null
        _connectionState.value = ConnectionState.DISCONNECTED
    }

    /**
     * Создание новой сессии (устройство)
     */
    fun createSession(deviceInfo: JSONObject) {
        if (_connectionState.value != ConnectionState.CONNECTED) {
            Log.w(TAG, "❌ Нет подключения к серверу")
            return
        }

        Log.i(TAG, "📱 Создание сессии...")

        val message = JSONObject().apply {
            put("type", "create_session")
            put("device_info", deviceInfo)
        }

        sendMessage(message)
    }

    /**
     * Отправка SDP offer
     */
    fun sendOffer(sdp: String) {
        if (sessionId == null) {
            Log.w(TAG, "❌ Нет активной сессии")
            return
        }

        Log.i(TAG, "📞 Отправка SDP Offer")

        val message = JSONObject().apply {
            put("type", "offer")
            put("session_id", sessionId)
            put("sdp", JSONObject().apply {
                put("type", "offer")
                put("sdp", sdp)
            })
        }

        sendMessage(message)
    }

    /**
     * Отправка ICE кандидата
     */
    fun sendIceCandidate(candidate: String, sdpMid: String, sdpMLineIndex: Int) {
        if (sessionId == null) {
            Log.w(TAG, "❌ Нет активной сессии")
            return
        }

        Log.d(TAG, "🧊 Отправка ICE candidate")

        val message = JSONObject().apply {
            put("type", "ice_candidate")
            put("session_id", sessionId)
            put("candidate", JSONObject().apply {
                put("candidate", candidate)
                put("sdpMid", sdpMid)
                put("sdpMLineIndex", sdpMLineIndex)
            })
        }

        sendMessage(message)
    }

    /**
     * Завершение сессии
     */
    fun hangup() {
        if (sessionId == null) {
            Log.w(TAG, "❌ Нет активной сессии")
            return
        }

        Log.i(TAG, "📴 Завершение сессии")

        val message = JSONObject().apply {
            put("type", "hangup")
            put("session_id", sessionId)
        }

        sendMessage(message)
        sessionId = null
    }

    /**
     * Отправка сообщения через WebSocket
     */
    private fun sendMessage(message: JSONObject) {
        if (_connectionState.value != ConnectionState.CONNECTED) {
            Log.w(TAG, "❌ Нет подключения для отправки сообщения")
            return
        }

        val messageText = message.toString()
        Log.d(TAG, "📤 Отправка сообщения: $messageText")

        webSocket?.send(messageText)
    }

    /**
     * Обработка входящих сообщений
     */
    private fun handleMessage(messageText: String) {
        try {
            val message = JSONObject(messageText)
            val type = message.optString("type")

            Log.d(TAG, "🔍 Обработка сообщения типа: $type")

            when (type) {
                "client_registered" -> {
                    clientId = message.optString("client_id")
                    Log.i(TAG, "🆔 Зарегистрирован как клиент: $clientId")
                }

                "session_created" -> {
                    sessionId = message.optString("session_id")
                    Log.i(TAG, "✅ Сессия создана: $sessionId")
                    onSessionCreated?.invoke(sessionId!!)
                }

                "operator_joined" -> {
                    Log.i(TAG, "👤 Оператор подключился")
                    onOperatorJoined?.invoke()
                }

                "answer" -> {
                    Log.i(TAG, "📞 Получен SDP Answer")
                    onMessageReceived?.invoke(message)
                }

                "ice_candidate" -> {
                    Log.d(TAG, "🧊 Получен ICE candidate")
                    onMessageReceived?.invoke(message)
                }

                "hangup" -> {
                    Log.i(TAG, "📴 Сессия завершена оператором")
                    sessionId = null
                    onMessageReceived?.invoke(message)
                }

                "error" -> {
                    val errorMessage = message.optString("message", "Неизвестная ошибка")
                    Log.e(TAG, "❌ Ошибка сервера: $errorMessage")
                }

                else -> {
                    Log.w(TAG, "⚠️ Неизвестный тип сообщения: $type")
                }
            }

        } catch (e: Exception) {
            Log.e(TAG, "❌ Ошибка парсинга сообщения: ${e.message}", e)
        }
    }

    /**
     * Планирование переподключения
     */
    private fun scheduleReconnect() {
        if (_connectionState.value == ConnectionState.DISCONNECTED) {
            return // Не переподключаемся если отключились вручную
        }

        Log.i(TAG, "🔄 Планирование переподключения через ${RECONNECT_DELAY}мс")

        scope.launch {
            delay(RECONNECT_DELAY)
            if (_connectionState.value == ConnectionState.ERROR) {
                Log.i(TAG, "🔄 Попытка переподключения...")
                connect()
            }
        }
    }

    /**
     * Получение информации о текущей сессии
     */
    fun getCurrentSessionId(): String? = sessionId

    /**
     * Проверка активности сессии
     */
    fun hasActiveSession(): Boolean = sessionId != null

    /**
     * Освобождение ресурсов
     */
    fun destroy() {
        disconnect()
        scope.cancel()
    }
}
