package com.example.godeye

import android.app.Application
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.core.content.edit
import com.example.godeye.managers.*
import com.example.godeye.models.*
import com.example.godeye.services.SocketService
import com.example.godeye.utils.Logger
import com.example.godeye.utils.generateDeviceId
import com.example.godeye.utils.getPreferences
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * MainViewModel - Главная ViewModel, интегрирующая все компоненты согласно ТЗ
 * Архитектура: MVVM с LiveData/StateFlow
 * Сеть: Socket.IO для сигнализации, WebRTC для медиа
 */
class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val context = getApplication<Application>()

    // Управляющие компоненты согласно ТЗ
    private var socketService: SocketService? = null
    private var sessionManager: SessionManager = SessionManager()
    private var permissionManager: PermissionManager = PermissionManager(context)
    private var camera2Manager: Camera2Manager = Camera2Manager(context)
    private var webRTCManager: WebRTCManager? = null

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

    private val _serverUrl = MutableStateFlow("")
    val serverUrl: StateFlow<String> = _serverUrl.asStateFlow()

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

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()

    // Управление сессиями согласно ТЗ
    private val _cameraRequest = MutableStateFlow<CameraRequest?>(null)
    val cameraRequest: StateFlow<CameraRequest?> = _cameraRequest.asStateFlow()

    private val _activeSessions = MutableStateFlow<Map<String, SessionInfo>>(emptyMap())
    val activeSessions: StateFlow<Map<String, SessionInfo>> = _activeSessions.asStateFlow()

    private val _isStreaming = MutableStateFlow(false)
    val isStreaming: StateFlow<Boolean> = _isStreaming.asStateFlow()

    // Разрешения согласно ТЗ
    val permissionsGranted = permissionManager.permissionsGranted
    val missingPermissions = permissionManager.missingPermissions

    // Камеры согласно ТЗ
    val availableCameras = camera2Manager.availableCameras
    val cameraState = camera2Manager.cameraState

    // Подключение к SocketService
    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Logger.step("SERVICE_CONNECTED", "SocketService connected")
            val binder = service as SocketService.LocalBinder
            socketService = binder.getService()
            setupServiceObservers()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Logger.step("SERVICE_DISCONNECTED", "SocketService disconnected")
            socketService = null
        }
    }

    init {
        Logger.step("VIEWMODEL_INIT", "MainViewModel initialization with full ТЗ architecture")
        initializeApp()
        bindToSocketService()
    }

    /**
     * Инициализация приложения согласно ТЗ
     */
    private fun initializeApp() {
        Logger.step("APP_INIT", "Initializing application with ТЗ requirements")

        // 1. Проверка разрешений (CAMERA, RECORD_AUDIO, INTERNET, FOREGROUND_SERVICE)
        permissionManager.checkPermissions()

        // 2. Генерация/загрузки Device ID
        val prefs = context.getPreferences()
        var deviceId = prefs.getString("device_id", null)
        if (deviceId == null) {
            deviceId = generateDeviceId()
            prefs.edit { putString("device_id", deviceId) }
        }
        _deviceId.value = deviceId

        // 3. Загрузка сохраненного URL сервера
        val savedUrl = prefs.getString("server_url", "http://192.168.219.108:3001") ?: ""
        _serverUrl.value = savedUrl

        // 4. Инициализация WebRTC
        initializeWebRTC()

        Logger.step("APP_INIT_COMPLETE", "Application initialized according to ТЗ")
        Logger.d("Configuration:")
        Logger.d("  Device ID: $deviceId")
        Logger.d("  Server URL: $savedUrl")
        Logger.d("  Available cameras: ${camera2Manager.getAvailableCameraTypes()}")
        Logger.d("  Permissions granted: ${permissionManager.permissionsGranted.value}")
    }

    /**
     * Подключение к SocketService для фоновой работы
     */
    private fun bindToSocketService() {
        val intent = Intent(context, SocketService::class.java)
        context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
    }

    /**
     * Настройка наблюдателей за SocketService - исправленная версия
     */
    private fun setupServiceObservers() {
        val service = socketService ?: return

        // Простое наблюдение за состоянием подключения без внутренних API
        viewModelScope.launch {
            while (true) {
                try {
                    val state = service.connectionState.value
                    if (_connectionState.value != state) {
                        _connectionState.value = state
                        Logger.step("CONNECTION_STATE_CHANGED", "Connection state: $state")
                    }
                    kotlinx.coroutines.delay(1000) // Проверяем каждую секунду
                } catch (e: Exception) {
                    Logger.error("CONNECTION_STATE_ERROR", "Error checking connection state", e)
                    break
                }
            }
        }

        // Простое наблюдение за запросами камеры
        viewModelScope.launch {
            while (true) {
                try {
                    val request = service.cameraRequests.value
                    if (_cameraRequest.value != request && request != null) {
                        Logger.step("CAMERA_REQUEST_RECEIVED",
                            "Camera request from ${request.operatorId} for ${request.cameraType}")
                        _cameraRequest.value = request
                    }
                    kotlinx.coroutines.delay(500) // Проверяем каждые полсекунды
                } catch (e: Exception) {
                    Logger.error("CAMERA_REQUEST_ERROR", "Error checking camera requests", e)
                    break
                }
            }
        }

        // Простое наблюдение за WebRTC событиями
        viewModelScope.launch {
            while (true) {
                try {
                    val event = service.webRTCEvents.value
                    if (event != null) {
                        handleWebRTCEvent(event)
                        // Очищаем событие после обработки
                        service.webRTCEvents as MutableStateFlow
                        (service.webRTCEvents as MutableStateFlow).value = null
                    }
                    kotlinx.coroutines.delay(100) // Проверяем каждые 100мс
                } catch (e: Exception) {
                    Logger.error("WEBRTC_EVENT_ERROR", "Error checking WebRTC events", e)
                    break
                }
            }
        }
    }

    /**
     * Инициализация WebRTC согласно ТЗ
     */
    private fun initializeWebRTC() {
        webRTCManager = WebRTCManager(context)
    }

    /**
     * Подключение к серверу согласно ТЗ (Socket.IO)
     */
    fun connectToServer() {
        Logger.step("CONNECT_TO_SERVER", "Connecting to backend server via Socket.IO")

        if (!permissionManager.checkCriticalPermissions()) {
            Logger.error("CONNECT_FAILED", "Critical permissions not granted", null)
            return
        }

        val url = _serverUrl.value
        if (url.isBlank()) {
            Logger.error("CONNECT_FAILED", "Server URL is empty", null)
            return
        }

        _isLoading.value = true

        viewModelScope.launch {
            try {
                // Запуск SocketService для фоновой работы
                val intent = Intent(context, SocketService::class.java)
                context.startForegroundService(intent)

                // Подключение через SocketService
                socketService?.connect(url, _deviceId.value)

                // Сохранение URL
                context.getPreferences().edit {
                    putString("server_url", url)
                }

                Logger.step("CONNECT_INITIATED", "Connection initiated to: $url")

            } catch (e: Exception) {
                Logger.error("CONNECT_ERROR", "Failed to connect to server", e)
                _connectionState.value = ConnectionState.ERROR
            } finally {
                _isLoading.value = false
            }
        }
    }

    /**
     * Принятие запроса камеры согласно ТЗ
     */
    fun acceptCameraRequest(sessionId: String, reason: String = "Accepted by user") {
        Logger.step("ACCEPT_CAMERA_REQUEST", "Accepting camera request: $sessionId")

        val request = _cameraRequest.value
        if (request?.sessionId != sessionId) {
            Logger.error("ACCEPT_FAILED", "Invalid session ID", null)
            return
        }

        viewModelScope.launch {
            try {
                // 1. Создание сессии в SessionManager
                sessionManager.createSession(sessionId, request.operatorId, request.cameraType)

                // 2. Отправка положительного ответа через SocketService
                socketService?.sendCameraResponse(sessionId, true, reason)

                // 3. Инициализация WebRTC соединения
                webRTCManager?.startStreaming(request.operatorId, request.cameraType)

                // 4. Очистка запроса
                _cameraRequest.value = null

                Logger.step("CAMERA_REQUEST_ACCEPTED", "Camera request accepted for session: $sessionId")

            } catch (e: Exception) {
                Logger.error("ACCEPT_REQUEST_ERROR", "Failed to accept camera request", e)
            }
        }
    }

    /**
     * Отклонение запроса камеры
     */
    fun rejectCameraRequest(sessionId: String, reason: String = "Rejected by user") {
        Logger.step("REJECT_CAMERA_REQUEST", "Rejecting camera request: $sessionId")

        socketService?.sendCameraResponse(sessionId, false, reason)
        _cameraRequest.value = null

        Logger.step("CAMERA_REQUEST_REJECTED", "Camera request rejected: $sessionId")
    }

    /**
     * Обработка WebRTC событий
     */
    private fun handleWebRTCEvent(event: com.example.godeye.services.WebRTCEvent) {
        when (event) {
            is com.example.godeye.services.WebRTCEvent.Connected -> {
                Logger.step("WEBRTC_CONNECTED", "WebRTC connected")
            }
            is com.example.godeye.services.WebRTCEvent.Disconnected -> {
                Logger.step("WEBRTC_DISCONNECTED", "WebRTC disconnected")
            }
            is com.example.godeye.services.WebRTCEvent.Error -> {
                Logger.step("WEBRTC_ERROR", "WebRTC error: ${event.message}")
            }
            else -> {
                Logger.step("WEBRTC_EVENT", "Unknown WebRTC event: $event")
            }
        }
    }

    /**
     * Остановка всех стримов
     */
    fun stopAllStreaming() {
        viewModelScope.launch {
            try {
                Logger.step("STOP_ALL_STREAMING", "Stopping all camera streaming")

                webRTCManager?.stopAllStreaming()

                _activeSessions.value = emptyMap()
                _isStreaming.value = false

                Logger.step("STOP_ALL_STREAMING_SUCCESS", "All streaming stopped successfully")

            } catch (e: Exception) {
                Logger.error("STOP_ALL_STREAMING_ERROR", "Failed to stop streaming", e)
            }
        }
    }

    /**
     * Переключение камеры
     */
    fun switchCamera(cameraType: String) {
        viewModelScope.launch {
            try {
                Logger.step("SWITCH_CAMERA", "Switching camera to: $cameraType")

                webRTCManager?.switchCamera()

                // Обновляем тип камеры в активных сессиях
                val updatedSessions = _activeSessions.value.mapValues { (_, sessionInfo) ->
                    sessionInfo.copy(cameraType = cameraType)
                }
                _activeSessions.value = updatedSessions

                Logger.step("SWITCH_CAMERA_SUCCESS", "Camera switched to: $cameraType")

            } catch (e: Exception) {
                Logger.error("SWITCH_CAMERA_ERROR", "Failed to switch camera", e)
            }
        }
    }

    /**
     * Завершение сессии
     */
    fun endCameraSession(sessionId: String) {
        Logger.step("END_SESSION", "Ending camera session: $sessionId")

        sessionManager.endSession(sessionId, "Ended by user")
        webRTCManager?.endSession()

        Logger.step("SESSION_ENDED", "Session ended: $sessionId")
    }

    /**
     * Отключение от сервера
     */
    fun disconnect() {
        Logger.step("DISCONNECT", "Disconnecting from server")

        socketService?.disconnect()
        sessionManager.endAllSessions("User disconnected")
        webRTCManager?.stopAllStreaming()

        _connectionState.value = ConnectionState.DISCONNECTED
        _isStreaming.value = false

        Logger.step("DISCONNECTED", "Disconnected from server")
    }

    /**
     * Обновление URL сервера
     */
    fun updateServerUrl(url: String) {
        _serverUrl.value = url
        context.getPreferences().edit {
            putString("server_url", url)
        }
        Logger.step("SERVER_URL_UPDATED", "Server URL updated: $url")
    }

    /**
     * Очистка запроса камеры
     */
    fun clearCameraRequest() {
        _cameraRequest.value = null
    }

    /**
     * Проверка разрешений
     */
    fun checkPermissions() {
        permissionManager.checkPermissions()
    }

    /**
     * Callback при получении разрешений
     */
    fun onPermissionsGranted() {
        Logger.step("VIEWMODEL_PERMISSIONS_GRANTED", "All permissions granted in ViewModel")
        permissionManager.checkPermissions()
    }

    /**
     * Запуск тестового стриминга камеры
     */
    fun startTestStreaming() {
        viewModelScope.launch {
            try {
                Logger.step("START_TEST_STREAMING", "Starting test camera streaming")

                // Создаем тестовую сессию
                val testSessionId = "test_session_${System.currentTimeMillis()}"
                val currentTime = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss", java.util.Locale.getDefault())
                    .format(java.util.Date())

                val testSessionInfo = SessionInfo(
                    sessionId = testSessionId,
                    deviceId = _deviceId.value,
                    operatorId = "test_operator",
                    cameraType = "back",
                    status = "streaming",
                    createdAt = currentTime
                )

                // Добавляем в активные сессии
                val currentSessions = _activeSessions.value.toMutableMap()
                currentSessions[testSessionId] = testSessionInfo
                _activeSessions.value = currentSessions

                _isStreaming.value = true

                // Инициализируем WebRTC если нужно
                if (webRTCManager == null) {
                    webRTCManager = WebRTCManager(context)
                }

                // Запускаем стриминг
                webRTCManager?.startStreaming("test_operator", "back")

                Logger.step("START_TEST_STREAMING_SUCCESS", "Test streaming started successfully")

            } catch (e: Exception) {
                Logger.error("START_TEST_STREAMING_ERROR", "Failed to start test streaming", e)
            }
        }
    }

    override fun onCleared() {
        Logger.step("VIEWMODEL_CLEARED", "MainViewModel cleared with ТЗ cleanup")

        sessionManager.endAllSessions("App closed")
        webRTCManager?.dispose()
        camera2Manager.release()

        super.onCleared()
    }
}
