package com.example.godeye.services

import android.app.*
import android.content.Context
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.example.godeye.MainActivity
import com.example.godeye.R
import com.example.godeye.managers.PermissionManager
import com.example.godeye.models.*
import com.example.godeye.utils.Constants
import com.example.godeye.utils.Logger
import com.example.godeye.utils.generateDeviceId
import com.example.godeye.utils.getAvailableCameraTypes
import com.google.gson.Gson
import com.google.gson.JsonObject
import io.socket.client.IO
import io.socket.client.Socket
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.net.URI

/**
 * Сервис для управления WebSocket соединением с backend сервером
 */
class SocketService : Service() {

    private val binder = LocalBinder()
    private var socket: Socket? = null
    private val gson = Gson()
    private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

    private lateinit var permissionManager: PermissionManager

    // StateFlows для отслеживания состояния
    private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED)
    val connectionState: StateFlow<ConnectionState> = _connectionState.asStateFlow()

    private val _deviceId = MutableStateFlow("")
    val deviceId: StateFlow<String> = _deviceId.asStateFlow()

    private val _error = MutableStateFlow<AppError?>(null)
    val error: StateFlow<AppError?> = _error.asStateFlow()

    // События для UI
    private val _cameraRequest = MutableStateFlow<CameraRequest?>(null)
    val cameraRequest: StateFlow<CameraRequest?> = _cameraRequest.asStateFlow()

    private val _webrtcOffer = MutableStateFlow<WebRTCMessage?>(null)
    val webrtcOffer: StateFlow<WebRTCMessage?> = _webrtcOffer.asStateFlow()

    private val _webrtcAnswer = MutableStateFlow<WebRTCMessage?>(null)
    val webrtcAnswer: StateFlow<WebRTCMessage?> = _webrtcAnswer.asStateFlow()

    private val _webrtcIceCandidate = MutableStateFlow<WebRTCMessage?>(null)
    val webrtcIceCandidate: StateFlow<WebRTCMessage?> = _webrtcIceCandidate.asStateFlow()

    private val _cameraSwitchRequest = MutableStateFlow<Pair<String, String>?>(null) // sessionId, newCameraType
    val cameraSwitchRequest: StateFlow<Pair<String, String>?> = _cameraSwitchRequest.asStateFlow()

    private val _sessionDisconnect = MutableStateFlow<String?>(null) // sessionId
    val sessionDisconnect: StateFlow<String?> = _sessionDisconnect.asStateFlow()

    inner class LocalBinder : Binder() {
        fun getService(): SocketService = this@SocketService
    }

    override fun onCreate() {
        super.onCreate()
        Logger.d("SocketService created")
        permissionManager = PermissionManager(this)
        _deviceId.value = generateDeviceId()
        createNotificationChannel()
    }

    override fun onBind(intent: Intent?): IBinder = binder

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        startForeground(Constants.FOREGROUND_SERVICE_ID, createNotification())
        return START_STICKY
    }

    /**
     * Подключиться к серверу
     */
    fun connect(serverUrl: String) {
        serviceScope.launch {
            try {
                _connectionState.value = ConnectionState.CONNECTING
                Logger.d("Connecting to server: $serverUrl")

                // Дополнительная проверка URL
                if (serverUrl.isBlank()) {
                    Logger.e("Server URL is empty")
                    _connectionState.value = ConnectionState.ERROR
                    _error.value = AppError.NetworkError
                    return@launch
                }

                Logger.d("Creating URI from: $serverUrl")
                val uri = URI.create(serverUrl)
                Logger.d("URI created successfully: $uri")

                Logger.d("Creating Socket.IO client")
                val options = IO.Options().apply {
                    timeout = 10000  // Увеличиваем таймаут до 10 секунд
                    reconnection = true
                    reconnectionDelay = 2000  // Увеличиваем задержку между попытками
                    reconnectionAttempts = 3  // Уменьшаем количество попыток
                    forceNew = true  // Принудительно создаваем новое соединение
                }

                socket = IO.socket(uri, options).apply {
                    Logger.d("Socket.IO client created, setting up listeners")
                    setupEventListeners()
                    Logger.d("Listeners set up, initiating connection")
                    connect()
                    Logger.d("Connection initiated")
                }

                // Добавляем таймаут для проверки подключения
                launch {
                    kotlinx.coroutines.delay(15000) // Ждем 15 секунд
                    if (_connectionState.value == ConnectionState.CONNECTING) {
                        Logger.w("Connection timeout after 15 seconds")
                        _connectionState.value = ConnectionState.ERROR
                        _error.value = AppError.SocketError("Connection timeout - server may be unreachable")
                        socket?.disconnect()
                    }
                }

            } catch (e: Exception) {
                Logger.e("Error connecting to server: ${e.message}", e)
                _connectionState.value = ConnectionState.ERROR
                _error.value = AppError.SocketError("Connection failed: ${e.message}")
            }
        }
    }

    /**
     * Отключиться от сервера
     */
    fun disconnect() {
        serviceScope.launch {
            try {
                socket?.disconnect()
                socket?.close()
                socket = null
                _connectionState.value = ConnectionState.DISCONNECTED
                Logger.d("Disconnected from server")
            } catch (e: Exception) {
                Logger.e("Error disconnecting from server", e)
            }
        }
    }

    /**
     * Настроить обработчики событий Socket.IO
     */
    private fun setupEventListeners() {
        socket?.apply {
            Logger.d("Setting up Socket.IO event listeners")

            on(Socket.EVENT_CONNECT) {
                Logger.d("✅ Socket connected successfully")
                _connectionState.value = ConnectionState.CONNECTED
                registerDevice()
            }

            on(Socket.EVENT_DISCONNECT) { args ->
                val reason = args.firstOrNull()?.toString() ?: "unknown"
                Logger.d("❌ Socket disconnected: $reason")
                _connectionState.value = ConnectionState.DISCONNECTED
            }

            on(Socket.EVENT_CONNECT_ERROR) { args ->
                val error = args.firstOrNull()?.toString() ?: "Unknown connection error"
                Logger.e("🔥 Socket connection error: $error")
                _connectionState.value = ConnectionState.ERROR
                _error.value = AppError.SocketError(error)
            }

            on(Constants.SocketEvents.REGISTER_SUCCESS) { args ->
                Logger.d("Device registered successfully")
                val data = args.firstOrNull()?.toString()
                Logger.d("Registration response: $data")
            }

            on(Constants.SocketEvents.REGISTER_ERROR) { args ->
                val error = args.firstOrNull()?.toString() ?: "Registration failed"
                Logger.e("Device registration error: $error")
                _error.value = AppError.SocketError(error)
            }

            on(Constants.SocketEvents.CAMERA_REQUEST) { args ->
                try {
                    val data = JSONObject(args[0].toString())
                    val request = CameraRequest(
                        sessionId = data.getString("sessionId"),
                        operatorId = data.getString("operatorId"),
                        cameraType = data.getString("cameraType")
                    )
                    Logger.d("Camera request received: $request")
                    _cameraRequest.value = request
                } catch (e: Exception) {
                    Logger.e("Error parsing camera request", e)
                }
            }

            on(Constants.SocketEvents.CAMERA_DISCONNECT) { args ->
                try {
                    val data = JSONObject(args[0].toString())
                    val sessionId = data.getString("sessionId")
                    Logger.d("Camera disconnect received for session: $sessionId")
                    _sessionDisconnect.value = sessionId
                } catch (e: Exception) {
                    Logger.e("Error parsing camera disconnect", e)
                }
            }

            on(Constants.SocketEvents.CAMERA_SWITCH) { args ->
                try {
                    val data = JSONObject(args[0].toString())
                    val sessionId = data.getString("sessionId")
                    val newCameraType = data.getString("newCameraType")
                    Logger.d("Camera switch request: $sessionId -> $newCameraType")
                    _cameraSwitchRequest.value = Pair(sessionId, newCameraType)
                } catch (e: Exception) {
                    Logger.e("Error parsing camera switch", e)
                }
            }

            on(Constants.SocketEvents.WEBRTC_OFFER) { args ->
                try {
                    val data = JSONObject(args[0].toString())
                    val message = WebRTCMessage(
                        sessionId = data.getString("sessionId"),
                        type = "offer",
                        sdp = data.getString("offer")
                    )
                    Logger.d("WebRTC offer received for session: ${message.sessionId}")
                    _webrtcOffer.value = message
                } catch (e: Exception) {
                    Logger.e("Error parsing WebRTC offer", e)
                }
            }

            on(Constants.SocketEvents.WEBRTC_ICE_CANDIDATE) { args ->
                try {
                    val data = JSONObject(args[0].toString())
                    val message = WebRTCMessage(
                        sessionId = data.getString("sessionId"),
                        type = "ice-candidate",
                        candidate = data.getString("candidate"),
                        sdpMid = data.getString("sdpMid"),
                        sdpMLineIndex = data.getInt("sdpMLineIndex")
                    )
                    Logger.d("WebRTC ICE candidate received for session: ${message.sessionId}")
                    _webrtcIceCandidate.value = message
                } catch (e: Exception) {
                    Logger.e("Error parsing WebRTC ICE candidate", e)
                }
            }
        }
    }

    /**
     * Зарегистрировать устройство на сервере
     */
    private fun registerDevice() {
        try {
            val cameraManager = getSystemService(Context.CAMERA_SERVICE) as android.hardware.camera2.CameraManager
            val deviceInfo = DeviceInfo(
                availableCameras = cameraManager.getAvailableCameraTypes()
            )

            val registrationData = JsonObject().apply {
                addProperty("deviceId", _deviceId.value)
                add("deviceInfo", gson.toJsonTree(deviceInfo))
            }

            socket?.emit(Constants.SocketEvents.REGISTER_ANDROID, registrationData)
            Logger.d("Device registration sent: $registrationData")

        } catch (e: Exception) {
            Logger.e("Error registering device", e)
            _error.value = AppError.SocketError("Failed to register device: ${e.message}")
        }
    }

    /**
     * Отправить ответ на запрос камеры
     */
    fun sendCameraResponse(sessionId: String, accepted: Boolean, reason: String? = null) {
        try {
            val response = JsonObject().apply {
                addProperty("sessionId", sessionId)
                addProperty("accepted", accepted)
                reason?.let { addProperty("reason", it) }
            }

            socket?.emit(Constants.SocketEvents.CAMERA_RESPONSE, response)
            Logger.d("Camera response sent: $response")

        } catch (e: Exception) {
            Logger.e("Error sending camera response", e)
            _error.value = AppError.SocketError("Failed to send camera response: ${e.message}")
        }
    }

    /**
     * Отправить WebRTC answer
     */
    fun sendWebRTCAnswer(sessionId: String, answer: String) {
        try {
            val data = JsonObject().apply {
                addProperty("sessionId", sessionId)
                addProperty("answer", answer)
            }

            socket?.emit(Constants.SocketEvents.WEBRTC_ANSWER, data)
            Logger.d("WebRTC answer sent for session: $sessionId")

        } catch (e: Exception) {
            Logger.e("Error sending WebRTC answer", e)
            _error.value = AppError.SocketError("Failed to send WebRTC answer: ${e.message}")
        }
    }

    /**
     * Отправить ICE candidate
     */
    fun sendIceCandidate(sessionId: String, candidate: String, sdpMid: String, sdpMLineIndex: Int) {
        try {
            val data = JsonObject().apply {
                addProperty("sessionId", sessionId)
                addProperty("candidate", candidate)
                addProperty("sdpMid", sdpMid)
                addProperty("sdpMLineIndex", sdpMLineIndex)
            }

            socket?.emit(Constants.SocketEvents.WEBRTC_ICE_CANDIDATE, data)
            Logger.d("ICE candidate sent for session: $sessionId")

        } catch (e: Exception) {
            Logger.e("Error sending ICE candidate", e)
        }
    }

    /**
     * Создать канал уведомлений
     */
    private fun createNotificationChannel() {
        val channel = NotificationChannel(
            Constants.NOTIFICATION_CHANNEL_ID,
            "GodEye Service",
            NotificationManager.IMPORTANCE_LOW
        ).apply {
            description = "Уведомления о состоянии подключения GodEye"
            setShowBadge(false)
        }

        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(channel)
    }

    /**
     * Создать уведомление для foreground service
     */
    private fun createNotification(): Notification {
        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        val statusText = when (_connectionState.value) {
            ConnectionState.CONNECTED -> "Подключено"
            ConnectionState.CONNECTING -> "Подключение..."
            ConnectionState.RECONNECTING -> "Переподключение..."
            ConnectionState.DISCONNECTED -> "Отключено"
            ConnectionState.ERROR -> "Ошибка подключения"
        }

        return NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNEL_ID)
            .setContentTitle("GodEye Signal Center")
            .setContentText("Статус: $statusText")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentIntent(pendingIntent)
            .setOngoing(true)
            .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
            .build()
    }

    /**
     * Обновить уведомление
     */
    private fun updateNotification() {
        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager.notify(Constants.FOREGROUND_SERVICE_ID, createNotification())
    }

    /**
     * Очистить события
     */
    fun clearCameraRequest() {
        _cameraRequest.value = null
    }

    fun clearWebRTCOffer() {
        _webrtcOffer.value = null
    }

    fun clearError() {
        _error.value = null
    }

    override fun onDestroy() {
        super.onDestroy()
        disconnect()
        Logger.d("SocketService destroyed")
    }
}
