package com.example.livingai.pages.camera

import android.Manifest
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.pm.ActivityInfo
import android.provider.MediaStore
import androidx.camera.core.CameraSelector
import androidx.camera.video.MediaStoreOutputOptions
import androidx.camera.video.Recording
import androidx.camera.video.VideoRecordEvent
import androidx.camera.view.CameraController
import androidx.camera.view.LifecycleCameraController
import androidx.camera.view.video.AudioConfig
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Stop
import androidx.compose.material.icons.filled.Videocam
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.navigation.NavController
import com.example.livingai.domain.ml.FeedbackState
import com.example.livingai.pages.components.CameraPreview
import com.example.livingai.pages.components.PermissionWrapper
import com.example.livingai.pages.navigation.Route
import com.example.livingai.ui.theme.RecordingRed
import com.example.livingai.utils.Constants
import com.example.livingai.utils.SetScreenOrientation
import org.koin.androidx.compose.koinViewModel
import kotlin.math.max

@SuppressLint("MissingPermission")
@Composable
fun VideoRecordScreen(
    viewModel: VideoViewModel = koinViewModel(),
    navController: NavController,
    animalId: String
) {
    SetScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
    
    val context = LocalContext.current
    val state by viewModel.state.collectAsState()
    var recording by remember { mutableStateOf<Recording?>(null) }
    
    var frameWidth by remember { mutableStateOf(0) }
    var frameHeight by remember { mutableStateOf(0) }
    var rotation by remember { mutableStateOf(0) }

    // We need RECORD_AUDIO permission for video with audio
    PermissionWrapper(
        permissions = listOf(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        )
    ) { 
        val controller = remember {
            LifecycleCameraController(context).apply {
                setEnabledUseCases(CameraController.VIDEO_CAPTURE or CameraController.IMAGE_ANALYSIS)
                cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            }
        }

        LaunchedEffect(state.recordedVideoUri) {
            state.recordedVideoUri?.let { uri ->
                navController.navigate(Route.ViewVideoScreen(videoUri = uri.toString(), shouldAllowRetake = true, animalId = animalId))
                viewModel.onEvent(VideoEvent.ClearRecordedVideo)
            }
        }

        Scaffold(
            floatingActionButton = {
                FloatingActionButton(
                    onClick = {
                        if (state.isRecording) {
                            recording?.stop()
                            viewModel.onEvent(VideoEvent.StopRecording)
                        } else {
                            val contentValues = ContentValues().apply {
                                put(MediaStore.MediaColumns.DISPLAY_NAME, "${animalId}_video_${System.currentTimeMillis()}")
                                put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
                                if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.P) {
                                    put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/LivingAI/Media/$animalId")
                                }
                            }

                            val mediaStoreOutputOptions = MediaStoreOutputOptions.Builder(
                                context.contentResolver,
                                MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                            )
                            .setContentValues(contentValues)
                            .build()

                            recording = controller.startRecording(
                                mediaStoreOutputOptions,
                                AudioConfig.create(true),
                                ContextCompat.getMainExecutor(context)
                            ) { recordEvent: VideoRecordEvent ->
                                when (recordEvent) {
                                    is VideoRecordEvent.Start -> {
                                        viewModel.onEvent(VideoEvent.StartRecording)
                                    }
                                    is VideoRecordEvent.Finalize -> {
                                        if (!recordEvent.hasError()) {
                                            val uri = recordEvent.outputResults.outputUri
                                            viewModel.onEvent(VideoEvent.VideoRecorded(uri))
                                        } else {
                                            viewModel.onEvent(VideoEvent.StopRecording)
                                            // Handle error
                                        }
                                    }
                                }
                            }
                        }
                    },
                    containerColor = if (state.isRecording) RecordingRed else FloatingActionButtonDefaults.containerColor
                ) {
                    Icon(
                        imageVector = if (state.isRecording) Icons.Default.Stop else Icons.Default.Videocam,
                        contentDescription = if (state.isRecording) "Stop Recording" else "Start Recording"
                    )
                }
            },
            floatingActionButtonPosition = FabPosition.Center
        ) { paddingValues ->
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                CameraPreview(
                    modifier = Modifier.fillMaxSize(),
                    controller = controller,
                    onFrame = { bitmap, imageRotation, focalLength ->
                        frameWidth = bitmap.width
                        frameHeight = bitmap.height
                        rotation = imageRotation
                        viewModel.onEvent(VideoEvent.FrameReceived(bitmap, imageRotation, focalLength = focalLength))
                    }
                )
                
                // Overlay
                Column(
                    modifier = Modifier.fillMaxSize()
                ) {
                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .fillMaxWidth()
                            .background(Color.Black.copy(alpha = 0.5f))
                    )
                    Spacer(
                        modifier = Modifier
                            .height(Constants.VIDEO_SILHOETTE_FRAME_HEIGHT) // Constant height for the transparent area
                            .fillMaxWidth()
                    )
                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .fillMaxWidth()
                            .background(Color.Black.copy(alpha = 0.5f))
                    )
                }

                // Feedback Text Overlay
                if (state.feedback !is FeedbackState.Idle && state.feedback !is FeedbackState.Optimal) {
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(top = 80.dp),
                        contentAlignment = Alignment.TopCenter
                    ) {
                        Text(
                            text = state.feedback.message,
                            color = Color.White,
                            style = MaterialTheme.typography.headlineMedium,
                            textAlign = TextAlign.Center,
                            modifier = Modifier
                                .background(Color.Black.copy(alpha = 0.6f))
                                .padding(horizontal = 16.dp, vertical = 8.dp)
                        )
                    }
                }

                // Bounding Box Overlay
                Canvas(modifier = Modifier.fillMaxSize()) {
                    val canvasWidth = size.width
                    val canvasHeight = size.height
                    
                    if (frameWidth > 0 && frameHeight > 0) {
                        // Determine source dimensions based on rotation
                        val isRotated = rotation == 90 || rotation == 270
                        val sourceWidth = if (isRotated) frameHeight.toFloat() else frameWidth.toFloat()
                        val sourceHeight = if (isRotated) frameWidth.toFloat() else frameHeight.toFloat()

                        // Calculate scale preserving aspect ratio (CenterCrop equivalent)
                        val scaleX = canvasWidth / sourceWidth
                        val scaleY = canvasHeight / sourceHeight
                        val scale = max(scaleX, scaleY)

                        // Calculate the dimensions of the scaled image
                        val scaledWidth = sourceWidth * scale
                        val scaledHeight = sourceHeight * scale

                        // Calculate the offset to center the image
                        val dx = (canvasWidth - scaledWidth) / 2
                        val dy = (canvasHeight - scaledHeight) / 2

                        // Draw framing box (debug/guide)
                        val targetHeight = Constants.VIDEO_SILHOETTE_FRAME_HEIGHT.toPx()
                        val targetTop = (canvasHeight - targetHeight) / 2
                        
                        drawRect(
                            color = Color.Blue,
                            topLeft = Offset(0f, targetTop),
                            size = Size(canvasWidth, targetHeight),
                            style = Stroke(width = 2.dp.toPx())
                        )

                        state.cowDetection?.let { result ->
                            val box = result.boundingBox
                            
                            val boxColor = if (state.feedback is FeedbackState.Optimal) Color.Green else Color.Yellow
                            
                            drawRect(
                                color = boxColor,
                                topLeft = Offset(
                                    x = box.left * scale + dx,
                                    y = box.top * scale + dy
                                ),
                                size = Size(
                                    width = box.width() * scale,
                                    height = box.height() * scale
                                ),
                                style = Stroke(width = 3.dp.toPx())
                            )
                        }
                    }
                }
            }
        }
    }
}
