package com.example.livingai.pages.camera

import android.graphics.Bitmap
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.livingai.domain.camera.*
import com.example.livingai.domain.model.camera.*
import com.example.livingai.utils.TiltSensorManager
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class CameraViewModel(
    private val orientationChecker: OrientationChecker,
    private val tiltChecker: TiltChecker,
    private val objectDetector: ObjectDetector,
    private val poseAnalyzer: PoseAnalyzer,
    private val captureHandler: CaptureHandler,
    private val measurementCalculator: MeasurementCalculator,
    private val tiltSensorManager: TiltSensorManager
) : ViewModel() {

    private val _uiState = MutableStateFlow(CameraUiState())
    val uiState: StateFlow<CameraUiState> = _uiState.asStateFlow()
    private val tilt = tiltSensorManager.tilt

    private var frameCounter = 0
    private val frameSkipInterval = 5

    init {
        tiltSensorManager.start()
    }

    override fun onCleared() {
        super.onCleared()
        tiltSensorManager.stop()
    }

    fun setRequiredOrientation(orientation: String) {
        val required = when (orientation.lowercase()) {
            "front", "back" -> CameraOrientation.PORTRAIT
            else -> CameraOrientation.LANDSCAPE
        }
        _uiState.value = _uiState.value.copy(
            requiredOrientation = required,
            targetOrientation = orientation
        )
    }

    fun processFrame(
        image: Bitmap, 
        deviceOrientation: Int,
        screenWidth: Float,
        screenHeight: Float
    ) {
        frameCounter = (frameCounter + 1) % frameSkipInterval
        if (frameCounter != 0) return

        viewModelScope.launch {
            val currentTilt = tilt.value
            val input = PipelineInput(
                image = image,
                deviceOrientation = deviceOrientation,
                deviceRoll = currentTilt.second,
                devicePitch = currentTilt.first,
                deviceAzimuth = currentTilt.third,
                requiredOrientation = _uiState.value.requiredOrientation,
                screenWidthPx = screenWidth,
                screenHeightPx = screenHeight,
                targetAnimal = "Cow", // Assuming Cow for now, can be parameter later
                orientation = _uiState.value.targetOrientation,
                previousDetectionResult = _uiState.value.lastDetectionResult
            )

            // Step 1: Check Orientation
            val orientationInstruction = orientationChecker.analyze(input)
            if (!orientationInstruction.isValid) {
                updateState(orientationInstruction)
                return@launch
            }

            // Step 2: Check Tilt
            val tiltInstruction = tiltChecker.analyze(input)
            if (!tiltInstruction.isValid) {
                updateState(tiltInstruction)
                return@launch
            }

            // Step 3: Detect Objects
            val detectionInstruction = objectDetector.analyze(input)
            if (!detectionInstruction.isValid) {
                updateState(detectionInstruction)
                return@launch
            }

            // Step 4: Check Pose (Silhouette matching)
            val poseInstruction = poseAnalyzer.analyze(input.copy(previousDetectionResult = detectionInstruction.result as? DetectionResult))
            if (!poseInstruction.isValid) {
                updateState(poseInstruction, detectionInstruction.result as? DetectionResult)
                return@launch
            }
            
            // All checks passed
            _uiState.value = _uiState.value.copy(
                currentInstruction = Instruction("Ready to capture", isValid = true),
                isReadyToCapture = true,
                lastDetectionResult = detectionInstruction.result as? DetectionResult
            )
        }
    }

    private fun updateState(instruction: Instruction, latestDetectionResult: DetectionResult? = null) {
        val detectionResult = (instruction.result as? DetectionResult) ?: latestDetectionResult
        _uiState.value = _uiState.value.copy(
            currentInstruction = instruction,
            isReadyToCapture = false,
            lastDetectionResult = detectionResult ?: _uiState.value.lastDetectionResult
        )
    }
    
    fun onCaptureClicked(
        image: Bitmap, 
        deviceOrientation: Int,
        screenWidth: Float,
        screenHeight: Float
    ) {
        viewModelScope.launch {
            val detectionResult = _uiState.value.lastDetectionResult ?: return@launch
            val currentTilt = tilt.value
            
             val input = PipelineInput(
                image = image,
                deviceOrientation = deviceOrientation,
                deviceRoll = currentTilt.second,
                devicePitch = currentTilt.first,
                deviceAzimuth = currentTilt.third,
                requiredOrientation = _uiState.value.requiredOrientation,
                screenWidthPx = screenWidth,
                screenHeightPx = screenHeight,
                targetAnimal = "Cow",
                orientation = _uiState.value.targetOrientation
            )

            val captureData = captureHandler.capture(input, detectionResult)
            
            _uiState.value = _uiState.value.copy(
                captureData = captureData,
                isPreviewMode = true
            )
        }
    }

    fun onReferenceObjectSelected(refObj: ReferenceObject, realHeight: Float) {
        val captureData = _uiState.value.captureData ?: return
        
        val realMetrics = measurementCalculator.calculateRealMetrics(
            targetHeight = realHeight,
            referenceObject = refObj,
            currentMetrics = captureData.animalMetrics
        )
        
        _uiState.value = _uiState.value.copy(
            realWorldMetrics = realMetrics
        )
    }
    
    fun resetCamera() {
        _uiState.value = _uiState.value.copy(
            isPreviewMode = false,
            captureData = null,
            realWorldMetrics = null,
            isReadyToCapture = false,
            currentInstruction = null
        )
    }
}


data class CameraUiState(
    val requiredOrientation: CameraOrientation = CameraOrientation.LANDSCAPE,
    val targetOrientation: String = "side",
    val currentInstruction: Instruction? = null,
    val isReadyToCapture: Boolean = false,
    val lastDetectionResult: DetectionResult? = null,
    val isPreviewMode: Boolean = false,
    val captureData: CaptureData? = null,
    val realWorldMetrics: RealWorldMetrics? = null
)
