package com.example.godeye.services

import android.app.*
import android.content.Intent
import android.graphics.SurfaceTexture
import android.os.Binder
import android.os.IBinder
import android.view.Surface
import androidx.core.app.NotificationCompat
import com.example.godeye.MainActivity
import com.example.godeye.R
import com.example.godeye.managers.CameraManager
import com.example.godeye.managers.SessionManager
import com.example.godeye.managers.WebRTCManager
import com.example.godeye.models.AppError
import com.example.godeye.models.WebRTCConnectionState
import com.example.godeye.utils.Constants
import com.example.godeye.utils.Logger
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

/**
 * Сервис для управления камерой и WebRTC соединениями
 */
class CameraService : Service() {

    private val binder = LocalBinder()
    private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    private lateinit var cameraManager: CameraManager
    private lateinit var webRTCManager: WebRTCManager
    private lateinit var sessionManager: SessionManager

    // Surface для WebRTC видео
    private var webRTCSurface: Surface? = null
    private var surfaceTexture: SurfaceTexture? = null

    // StateFlows для отслеживания состояния
    private val _isActive = MutableStateFlow(false)
    val isActive: StateFlow<Boolean> = _isActive.asStateFlow()

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

    // Callbacks для передачи WebRTC событий
    private var onWebRTCOfferCreated: ((String, String) -> Unit)? = null // sessionId, offer
    private var onWebRTCIceCandidateCreated: ((String, String, String, Int) -> Unit)? = null // sessionId, candidate, sdpMid, sdpMLineIndex

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

    override fun onCreate() {
        super.onCreate()
        Logger.d("CameraService created")

        cameraManager = CameraManager(this)
        webRTCManager = WebRTCManager(this)
        sessionManager = SessionManager()

        // Инициализация WebRTC
        webRTCManager.initialize()

        createNotificationChannel()
        observeManagerStates()
    }

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

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

    /**
     * Установить callbacks для WebRTC событий
     */
    fun setWebRTCCallbacks(
        onOfferCreated: (String, String) -> Unit,
        onIceCandidateCreated: (String, String, String, Int) -> Unit
    ) {
        this.onWebRTCOfferCreated = onOfferCreated
        this.onWebRTCIceCandidateCreated = onIceCandidateCreated
    }

    /**
     * Начать камера сессию
     */
    fun startCameraSession(sessionId: String, operatorId: String, cameraType: String) {
        serviceScope.launch {
            try {
                Logger.d("Starting camera session: $sessionId, camera: $cameraType")

                // Добавляем сессию в менеджер
                sessionManager.addSession(sessionId, operatorId, cameraType)

                // Создаем Surface для WebRTC
                setupWebRTCSurface()

                // Создаем WebRTC соединение
                webRTCManager.createPeerConnection(
                    onOfferCreated = { offer ->
                        onWebRTCOfferCreated?.invoke(sessionId, offer)
                    },
                    onAnswerCreated = { answer ->
                        // Ответ не используется, так как мы создаем offer
                    },
                    onIceCandidateCreated = { candidate, sdpMid, sdpMLineIndex ->
                        onWebRTCIceCandidateCreated?.invoke(sessionId, candidate, sdpMid, sdpMLineIndex)
                    }
                )

                // Создаем локальные медиа треки
                webRTCManager.createLocalMediaTracks(cameraType)

                // Открываем камеру
                webRTCSurface?.let { surface ->
                    cameraManager.openCamera(
                        cameraType = cameraType,
                        surface = surface,
                        onSuccess = {
                            Logger.d("Camera opened successfully for session: $sessionId")
                            _isActive.value = true

                            // Создаем WebRTC offer
                            webRTCManager.createOffer()
                        },
                        onError = { error ->
                            Logger.e("Failed to open camera for session: $sessionId")
                            _error.value = error
                            sessionManager.endSession(sessionId)
                        }
                    )
                } ?: run {
                    val error = AppError.CameraError("WebRTC surface not available")
                    _error.value = error
                    sessionManager.endSession(sessionId)
                }

            } catch (e: Exception) {
                Logger.e("Error starting camera session", e)
                _error.value = AppError.UnknownError(e)
                sessionManager.endSession(sessionId)
            }
        }
    }

    /**
     * Обработать WebRTC answer
     */
    fun handleWebRTCAnswer(sessionId: String, answer: String) {
        serviceScope.launch {
            try {
                Logger.d("Handling WebRTC answer for session: $sessionId")
                webRTCManager.handleAnswer(answer)
                sessionManager.updateWebRTCStatus(sessionId, true)
            } catch (e: Exception) {
                Logger.e("Error handling WebRTC answer", e)
                _error.value = AppError.WebRTCConnectionFailed
            }
        }
    }

    /**
     * Добавить ICE candidate
     */
    fun addIceCandidate(sessionId: String, candidate: String, sdpMid: String, sdpMLineIndex: Int) {
        serviceScope.launch {
            try {
                Logger.d("Adding ICE candidate for session: $sessionId")
                webRTCManager.addIceCandidate(candidate, sdpMid, sdpMLineIndex)
            } catch (e: Exception) {
                Logger.e("Error adding ICE candidate", e)
            }
        }
    }

    /**
     * Переключить камеру
     */
    fun switchCamera(sessionId: String, newCameraType: String) {
        serviceScope.launch {
            try {
                Logger.d("Switching camera for session $sessionId to $newCameraType")

                // Обновляем тип камеры в сессии
                sessionManager.switchCameraForSession(sessionId, newCameraType)

                // Переключаем камеру в WebRTC
                webRTCManager.switchCamera(newCameraType)

                // Переключаем физическую камеру
                webRTCSurface?.let { surface ->
                    cameraManager.switchCamera(
                        newCameraType = newCameraType,
                        surface = surface,
                        onSuccess = {
                            Logger.d("Camera switched successfully to: $newCameraType")
                        },
                        onError = { error ->
                            Logger.e("Failed to switch camera to: $newCameraType")
                            _error.value = error
                        }
                    )
                }

            } catch (e: Exception) {
                Logger.e("Error switching camera", e)
                _error.value = AppError.CameraError("Failed to switch camera: ${e.message}")
            }
        }
    }

    /**
     * Завершить сессию
     */
    fun endSession(sessionId: String) {
        serviceScope.launch {
            try {
                Logger.d("Ending session: $sessionId")

                // Закрываем камеру
                cameraManager.closeCamera()

                // Закрываем WebRTC соединение
                webRTCManager.close()

                // Удаляем сессию
                sessionManager.endSession(sessionId)

                // Очищаем Surface
                cleanupWebRTCSurface()

                _isActive.value = false
                Logger.d("Session ended successfully: $sessionId")

                // Если нет активных сессий, останавливаем сервис
                if (!sessionManager.hasActiveSessions()) {
                    stopSelf()
                }

            } catch (e: Exception) {
                Logger.e("Error ending session", e)
            }
        }
    }

    /**
     * Завершить все сессии
     */
    fun endAllSessions() {
        serviceScope.launch {
            try {
                Logger.d("Ending all sessions")

                // Закрываем камеру
                cameraManager.closeCamera()

                // Закрываем WebRTC соединение
                webRTCManager.close()

                // Удаляем все сессии
                sessionManager.endAllSessions()

                // Очищаем Surface
                cleanupWebRTCSurface()

                _isActive.value = false
                Logger.d("All sessions ended successfully")

                stopSelf()

            } catch (e: Exception) {
                Logger.e("Error ending all sessions", e)
            }
        }
    }

    /**
     * Настроить Surface для WebRTC
     */
    private fun setupWebRTCSurface() {
        try {
            // Создаем SurfaceTexture для WebRTC
            surfaceTexture = SurfaceTexture(0).apply {
                setDefaultBufferSize(1280, 720)
            }
            webRTCSurface = Surface(surfaceTexture)
            Logger.d("WebRTC surface created successfully")
        } catch (e: Exception) {
            Logger.e("Error creating WebRTC surface", e)
            _error.value = AppError.CameraError("Failed to create WebRTC surface: ${e.message}")
        }
    }

    /**
     * Очистить WebRTC Surface
     */
    private fun cleanupWebRTCSurface() {
        try {
            webRTCSurface?.release()
            webRTCSurface = null

            surfaceTexture?.release()
            surfaceTexture = null

            Logger.d("WebRTC surface cleaned up")
        } catch (e: Exception) {
            Logger.e("Error cleaning up WebRTC surface", e)
        }
    }

    /**
     * Наблюдать за состояниями менеджеров
     */
    private fun observeManagerStates() {
        serviceScope.launch {
            // Наблюдаем за ошибками камеры
            cameraManager.error.collect { error ->
                error?.let {
                    _error.value = it
                    Logger.e("Camera manager error: $it")
                }
            }
        }

        serviceScope.launch {
            // Наблюдаем за ошибками WebRTC
            webRTCManager.error.collect { error ->
                error?.let {
                    _error.value = it
                    Logger.e("WebRTC manager error: $it")
                }
            }
        }

        serviceScope.launch {
            // Наблюдаем за состоянием WebRTC соединения
            webRTCManager.connectionState.collect { state ->
                Logger.d("WebRTC connection state: $state")
                when (state) {
                    WebRTCConnectionState.CONNECTED -> {
                        // Обновляем статус всех активных сессий
                        sessionManager.activeSessions.value.forEach { session ->
                            sessionManager.updateWebRTCStatus(session.sessionId, true)
                        }
                    }
                    WebRTCConnectionState.FAILED,
                    WebRTCConnectionState.DISCONNECTED -> {
                        // Обновляем статус всех активных сессий
                        sessionManager.activeSessions.value.forEach { session ->
                            sessionManager.updateWebRTCStatus(session.sessionId, false)
                        }
                    }
                    else -> { /* Игнорируем другие состояния */ }
                }
            }
        }
    }

    /**
     * Получить менеджер сессий
     */
    fun getSessionManager(): SessionManager = sessionManager

    /**
     * Создать канал уведомлений
     */
    private fun createNotificationChannel() {
        val channel = NotificationChannel(
            "${Constants.NOTIFICATION_CHANNEL_ID}_camera",
            "GodEye Camera 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 activeSessionsCount = sessionManager.getActiveSessionCount()
        val statusText = if (activeSessionsCount > 0) {
            "Активных сессий: $activeSessionsCount"
        } else {
            "Камера готова к работе"
        }

        return NotificationCompat.Builder(this, "${Constants.NOTIFICATION_CHANNEL_ID}_camera")
            .setContentTitle("GodEye Camera")
            .setContentText(statusText)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentIntent(pendingIntent)
            .setOngoing(true)
            .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
            .build()
    }

    /**
     * Очистить ошибку
     */
    fun clearError() {
        _error.value = null
        cameraManager.clearError()
        webRTCManager.clearError()
    }

    override fun onDestroy() {
        super.onDestroy()
        serviceScope.launch {
            endAllSessions()
        }
        Logger.d("CameraService destroyed")
    }
}
