package com.joe.camera.webcam

import android.app.Application
import android.content.pm.PackageManager
import androidx.camera.core.CameraSelector
import androidx.camera.view.PreviewView
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.viewModelScope
import com.joe.camera.webcam.ble.BleController
import com.joe.camera.webcam.camera.CameraController
import com.joe.camera.webcam.data.MediaRepository
import com.joe.camera.webcam.model.*
import com.joe.camera.webcam.system.ScreenController
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class MainUiState(
    val cameraState: CameraState = CameraState.FREE,
    val remoteMode: Boolean = false,
    val previewPaused: Boolean = false,
    val blackScreen: Boolean = false,
    val message: String? = null,
    val media: List<MediaItem> = emptyList(),
)

class MainViewModel(application: Application) : AndroidViewModel(application) {
    private val preferences = application.getSharedPreferences("webcam", 0)
    private val repository = MediaRepository(application)
    private val screenController = ScreenController(application)
    private val _uiState = MutableStateFlow(MainUiState(remoteMode = preferences.getBoolean("remote_mode", false)))
    val uiState = _uiState.asStateFlow()
    var selectedMedia: MediaItem? = null
        private set

    private val cameraController = CameraController(application, ::updateCameraState, ::message)
    private val bleController = BleController(application, ::handleRemoteCommand, ::updateCameraState, ::message)

    init { screenController.prepare() }

    fun startBle() { if (_uiState.value.remoteMode) bleController.startCentral() else bleController.startPeripheral() }
    fun bindCamera(owner: LifecycleOwner, view: PreviewView) { if (!_uiState.value.remoteMode) cameraController.bind(owner, view) }
    fun switchLens(front: Boolean) = cameraController.switchLens(if (front) CameraSelector.LENS_FACING_FRONT else CameraSelector.LENS_FACING_BACK)
    fun takePicture() { if (!_uiState.value.remoteMode && _uiState.value.cameraState == CameraState.FREE) cameraController.takePicture() }
    fun toggleRecording() {
        if (_uiState.value.remoteMode) bleController.sendCommand(RemoteCommand.VOLUME_UP)
        else if (_uiState.value.cameraState != CameraState.WORKING) cameraController.toggleRecording()
    }
    fun stopRecording() { cameraController.stopRecording() }
    fun exitAppWhenRecordingSaved(onReadyToExit: () -> Unit) {
        if (_uiState.value.remoteMode) onReadyToExit() else cameraController.stopRecording(onReadyToExit)
    }
    fun togglePreview() { cameraController.togglePreview(); _uiState.value = _uiState.value.copy(previewPaused = cameraController.previewPaused) }
    fun setCameraZoom(value: Float) = cameraController.setLinearZoom(value)
    fun toggleRemoteMode() {
        val remote = !_uiState.value.remoteMode
        preferences.edit().putBoolean("remote_mode", remote).apply()
        _uiState.value = _uiState.value.copy(remoteMode = remote, cameraState = CameraState.FREE)
        cameraController.release()
        if (remote) bleController.startCentral() else bleController.startPeripheral()
    }
    fun toggleBlackScreen() {
        val off = !_uiState.value.blackScreen
        _uiState.value = _uiState.value.copy(blackScreen = off)
        viewModelScope.launch(Dispatchers.IO) {
            val mode = screenController.setPhysicalScreen(off)
            message(when (mode) {
                ScreenControlMode.SHIZUKU -> if (off) "已通过 Shizuku 关闭显示" else "已通过 Shizuku 恢复显示"
                ScreenControlMode.ROOT -> if (off) "已通过 root 关闭显示" else "已通过 root 恢复显示"
                ScreenControlMode.OVERLAY -> if (off) "已使用应用内黑屏" else "显示已恢复"
            })
        }
    }
    fun loadMedia() = viewModelScope.launch(Dispatchers.IO) { _uiState.value = _uiState.value.copy(media = repository.loadMedia()) }
    fun selectMedia(item: MediaItem) { selectedMedia = item }
    fun deleteSelected(): Boolean {
        val item = selectedMedia ?: return false
        val deleted = repository.delete(item)
        if (deleted) { selectedMedia = null; loadMedia() }
        return deleted
    }
    fun clearMessage() { _uiState.value = _uiState.value.copy(message = null) }
    fun hasFrontCamera(): Boolean = getApplication<Application>().packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)

    private fun handleRemoteCommand(command: RemoteCommand) = when (command) {
        RemoteCommand.VOLUME_UP, RemoteCommand.RECORD_VIDEO -> toggleRecording()
        RemoteCommand.VOLUME_DOWN -> toggleBlackScreen()
        RemoteCommand.OPEN_SETTING -> message("请在设备上打开相机设置")
    }
    private fun updateCameraState(state: CameraState) { _uiState.value = _uiState.value.copy(cameraState = state); bleController.publishState(state) }
    private fun message(text: String) { _uiState.value = _uiState.value.copy(message = text) }

    override fun onCleared() { cameraController.release(); bleController.release(); screenController.release(); super.onCleared() }
}
