package com.example.livingai.pages.camera

import android.content.ContentValues
import android.graphics.Bitmap
import android.graphics.Matrix
import android.graphics.RectF
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.camera.core.ImageProxy
import androidx.camera.view.LifecycleCameraController
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Camera
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.exifinterface.media.ExifInterface
import androidx.navigation.NavController
import com.example.livingai.domain.camera.RealWorldMetrics
import com.example.livingai.domain.model.camera.*
import com.example.livingai.pages.components.CameraPreview
import com.example.livingai.pages.components.PermissionWrapper
import com.example.livingai.utils.SilhouetteManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.androidx.compose.koinViewModel
import java.io.OutputStream
import kotlin.math.max

@Composable
fun CameraCaptureScreen(
    navController: NavController,
    orientation: String?,
    animalId: String,
    viewModel: CameraViewModel = koinViewModel()
) {
    val uiState by viewModel.uiState.collectAsState()
    val scope = rememberCoroutineScope()
    val context = LocalContext.current

    LaunchedEffect(orientation) {
        if (orientation != null) {
             viewModel.setRequiredOrientation(orientation)
        }
    }

    PermissionWrapper {
        if (uiState.isPreviewMode && uiState.captureData != null) {
            CapturePreviewScreen(
                captureData = uiState.captureData!!,
                realWorldMetrics = uiState.realWorldMetrics,
                onRetake = { viewModel.resetCamera() },
                onSelectReference = { ref, height ->
                    viewModel.onReferenceObjectSelected(ref, height)
                },
                onAccept = {
                    scope.launch {
                        val bitmap = uiState.captureData!!.image
                        val filename = "${animalId}_${orientation ?: "unknown"}.jpg"
                        
                        var uri: Uri? = null
                        
                        withContext(Dispatchers.IO) {
                            val contentValues = ContentValues().apply {
                                put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
                                put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                    put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/LivingAI/$animalId")
                                }
                            }
                            
                            val imageUri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
                            
                            if (imageUri != null) {
                                val outputStream: OutputStream? = context.contentResolver.openOutputStream(imageUri)
                                outputStream?.use { out ->
                                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)
                                }
                                
                                // Write Exif metadata for bounding box
                                val detection = uiState.lastDetectionResult
                                val analysisSize = uiState.analysisSize
                                
                                var bounds = detection?.animalBounds
                                
                                if (bounds != null && analysisSize != null) {
                                     // Scale bounds to captured image size
                                     val scaleX = bitmap.width.toFloat() / analysisSize.width
                                     val scaleY = bitmap.height.toFloat() / analysisSize.height
                                     bounds = RectF(
                                         bounds.left * scaleX,
                                         bounds.top * scaleY,
                                         bounds.right * scaleX,
                                         bounds.bottom * scaleY
                                     )
                                }

                                if (bounds != null) {
                                    try {
                                        context.contentResolver.openFileDescriptor(imageUri, "rw")?.use { fd ->
                                            val exif = ExifInterface(fd.fileDescriptor)
                                            exif.setAttribute(ExifInterface.TAG_USER_COMMENT, "${bounds.left},${bounds.top},${bounds.right},${bounds.bottom}")
                                            exif.saveAttributes()
                                        }
                                    } catch (e: Exception) {
                                        e.printStackTrace()
                                    }
                                }

                                uri = imageUri
                            }
                        }
                        
                        if (uri != null) {
                            navController.previousBackStackEntry?.savedStateHandle?.set("newImageUri", uri.toString())
                            navController.previousBackStackEntry?.savedStateHandle?.set("newImageOrientation", orientation)
                            navController.popBackStack()
                        }
                    }
                }
            )
        } else {
            ActiveCameraScreen(
                uiState = uiState,
                viewModel = viewModel,
            )
        }
    }
}

@Composable
fun ActiveCameraScreen(
    uiState: CameraUiState,
    viewModel: CameraViewModel,
) {
    val context = LocalContext.current
    val configuration = LocalConfiguration.current
    val density = LocalDensity.current

    val screenWidthPx = with(density) { configuration.screenWidthDp.dp.toPx() }
    val screenHeightPx = with(density) { configuration.screenHeightDp.dp.toPx() }

    val screenWidthState = rememberUpdatedState(screenWidthPx)
    val screenHeightState = rememberUpdatedState(screenHeightPx)

    var analysisImageSize by remember { mutableStateOf(Size(0f, 0f)) }

    val controller = remember {
        LifecycleCameraController(context).apply {
            setEnabledUseCases(LifecycleCameraController.IMAGE_ANALYSIS or LifecycleCameraController.IMAGE_CAPTURE)
            setImageAnalysisAnalyzer(
                ContextCompat.getMainExecutor(context)
            ) { imageProxy ->
                val bitmap = imageProxy.toBitmap()
                val rotation = imageProxy.imageInfo.rotationDegrees
                val rotatedBitmap = rotateBitmap(bitmap, rotation)
                analysisImageSize = Size(rotatedBitmap.width.toFloat(), rotatedBitmap.height.toFloat())

                viewModel.processFrame(
                    image = rotatedBitmap,
                    deviceOrientation = rotation,
                    screenWidth = screenWidthState.value,
                    screenHeight = screenHeightState.value
                )
                imageProxy.close()
            }
        }
    }

    fun captureImage() {
        val executor = ContextCompat.getMainExecutor(context)
        controller.takePicture(
            executor,
            object : androidx.camera.core.ImageCapture.OnImageCapturedCallback() {
                override fun onCaptureSuccess(image: ImageProxy) {
                    val bitmap = image.toBitmap()
                    val rotation = image.imageInfo.rotationDegrees
                    val rotatedBitmap = rotateBitmap(bitmap, rotation)

                    viewModel.onCaptureClicked(
                        image = rotatedBitmap,
                        deviceOrientation = rotation,
                        screenWidth = screenWidthState.value,
                        screenHeight = screenHeightState.value
                    )
                    image.close()
                }
                override fun onError(exception: androidx.camera.core.ImageCaptureException) {
                    // Handle error
                }
            }
        )
    }

    LaunchedEffect(uiState.shouldCapture) {
        if (uiState.shouldCapture) {
            captureImage()
            viewModel.onCaptureTriggered()
        }
    }

    Scaffold(
        floatingActionButton = {
            if (uiState.isReadyToCapture && !uiState.isAutoCaptureOn) {
                FloatingActionButton(onClick = { captureImage() }) {
                    Icon(Icons.Default.Camera, contentDescription = "Capture")
                }
            }
        },
        floatingActionButtonPosition = FabPosition.Center
    ) { _ ->
        Box(modifier = Modifier.fillMaxSize()) {
            CameraPreview(
                modifier = Modifier.fillMaxSize(),
                controller = controller
            )

            // Silhouette Overlay
            if (uiState.targetOrientation.isNotEmpty()) {
                val silhouette = SilhouetteManager.getOriginal(uiState.targetOrientation)
                val silhouetteData = SilhouetteManager.getSilhouette(uiState.targetOrientation)

                if (silhouette != null) {
                     Image(
                        bitmap = silhouette.asImageBitmap(),
                        contentDescription = "Silhouette",
                        modifier = Modifier.fillMaxSize().alpha(0.3f),
                        contentScale = ContentScale.Fit
                    )
                }

                if (silhouetteData != null) {

                    if (silhouetteData.signedMask?.debugBitmap != null) {

                        val bbox = silhouetteData.boundingBox

                        Box(modifier = Modifier.fillMaxSize()) {

                            // Bounding box outline (same coordinate system)
                            Canvas(modifier = Modifier.fillMaxSize()) {
                                drawRect(
                                    color = Color.Red,
                                    topLeft = Offset(bbox.left, bbox.top),
                                    size = Size(bbox.width(), bbox.height()),
                                    style = Stroke(width = 2.dp.toPx())
                                )
                            }
                        }
                    }

                }
            }

            // Overlays
            uiState.currentInstruction?.let { instruction ->
                InstructionOverlay(
                    instruction = instruction,
                    modifier = Modifier.align(Alignment.Center)
                )
            }

            // Bounding Boxes Overlay for active detection
            uiState.lastDetectionResult?.let { detection ->
                 DetectionOverlay(
                     detection = detection,
                     imageWidth = analysisImageSize.width.toInt(),
                     imageHeight = analysisImageSize.height.toInt(),
                     modifier = Modifier.fillMaxSize()
                 )
            }
        }
    }
}

@Composable
fun InstructionOverlay(
    instruction: Instruction,
    modifier: Modifier = Modifier
) {
    if (instruction.isValid && instruction.message == "Ready to capture") return

    Column(
        modifier = modifier
            .fillMaxWidth()
            .padding(32.dp)
            .background(Color.Black.copy(alpha = 0.6f), RoundedCornerShape(16.dp))
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        if (!instruction.isValid) {
            Text(
                text = instruction.message,
                style = MaterialTheme.typography.titleLarge,
                color = Color.White,
                textAlign = TextAlign.Center
            )
            // Visual GIF logic would go here using instruction.animationResId
        }
    }
}

@Composable
fun DetectionOverlay(
    detection: DetectionResult,
    imageWidth: Int,
    imageHeight: Int,
    modifier: Modifier = Modifier
) {
    if (imageWidth == 0 || imageHeight == 0) return

    Canvas(modifier = modifier) {
        val canvasWidth = size.width
        val canvasHeight = size.height

        // This calculation assumes the camera preview's scale type is `FILL_CENTER`.
        // It maintains the aspect ratio of the image and centers it.
        val widthRatio = canvasWidth / imageWidth
        val heightRatio = canvasHeight / imageHeight
        val scale = max(widthRatio, heightRatio)

        val offsetX = (canvasWidth - imageWidth * scale) / 2f
        val offsetY = (canvasHeight - imageHeight * scale) / 2f

        // Helper to transform coordinates
        val transform: (RectF) -> RectF = { box ->
            RectF(
                box.left * scale + offsetX,
                box.top * scale + offsetY,
                box.right * scale + offsetX,
                box.bottom * scale + offsetY
            )
        }

        // Draw animal box (Yellow)
        detection.animalBounds?.let {
            val transformedBox = transform(it)
            drawRect(
                color = Color.Yellow,
                topLeft = Offset(transformedBox.left, transformedBox.top),
                size = Size(transformedBox.width(), transformedBox.height()),
                style = Stroke(width = 2.dp.toPx())
            )
        }

        // Draw reference object boxes (Cyan)
        detection.referenceObjects.forEach { refObject ->
            val transformedBox = transform(refObject.bounds)
            drawRect(
                color = Color.Cyan,
                topLeft = Offset(transformedBox.left, transformedBox.top),
                size = Size(transformedBox.width(), transformedBox.height()),
                style = Stroke(width = 2.dp.toPx())
            )
        }
    }
}

@Composable
fun CapturePreviewScreen(
    captureData: CaptureData,
    realWorldMetrics: RealWorldMetrics?,
    onRetake: () -> Unit,
    onSelectReference: (ReferenceObject, Float) -> Unit,
    onAccept: () -> Unit
) {
    var showDialog by remember { mutableStateOf(false) }
    var selectedRefObject by remember { mutableStateOf<ReferenceObject?>(null) }
    var inputHeight by remember { mutableStateOf("") }

    if (showDialog && selectedRefObject != null) {
        AlertDialog(
            onDismissRequest = { showDialog = false },
            title = { Text("Enter Real Height") },
            text = {
                OutlinedTextField(
                    value = inputHeight,
                    onValueChange = { inputHeight = it },
                    label = { Text("Height (cm)") }
                )
            },
            confirmButton = {
                Button(onClick = {
                    inputHeight.toFloatOrNull()?.let {
                        onSelectReference(selectedRefObject!!, it)
                    }
                    showDialog = false
                }) {
                    Text("Calculate")
                }
            }
        )
    }

    Column(modifier = Modifier.fillMaxSize()) {
        Box(modifier = Modifier.weight(1f)) {
            Image(
                bitmap = captureData.image.asImageBitmap(),
                contentDescription = "Captured Image",
                modifier = Modifier.fillMaxSize(),
                contentScale = ContentScale.Fit
            )

            realWorldMetrics?.let { metrics ->
                Column(
                    modifier = Modifier
                        .align(Alignment.TopStart)
                        .padding(16.dp)
                        .background(Color.Black.copy(alpha = 0.7f), RoundedCornerShape(8.dp))
                        .padding(8.dp)
                ) {
                    Text("Height: %.2f %s".format(metrics.height, metrics.unit), color = Color.White)
                    Text("Width: %.2f %s".format(metrics.width, metrics.unit), color = Color.White)
                    Text("Distance: %.2f".format(metrics.distance), color = Color.White)
                }
            }
        }

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Button(onClick = onRetake) {
                Icon(Icons.Default.Refresh, contentDescription = null)
                Spacer(Modifier.width(8.dp))
                Text("Retake")
            }

            Button(onClick = onAccept) {
                Icon(Icons.Default.Check, contentDescription = null)
                Spacer(Modifier.width(8.dp))
                Text("Accept")
            }
        }
    }
}

fun rotateBitmap(bitmap: Bitmap, degrees: Int): Bitmap {
    val matrix = Matrix()
    matrix.postRotate(degrees.toFloat())
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}
