package com.example.livingai.pages.components

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.hardware.camera2.CameraCharacteristics
import android.util.SizeF
import android.view.ViewGroup
import androidx.annotation.OptIn
import androidx.camera.camera2.interop.Camera2CameraInfo
import androidx.camera.camera2.interop.ExperimentalCamera2Interop
import androidx.camera.core.CameraSelector
import androidx.camera.view.LifecycleCameraController
import androidx.camera.view.PreviewView
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.viewinterop.AndroidView
import kotlinx.coroutines.delay
import java.util.concurrent.Executors

@OptIn(ExperimentalCamera2Interop::class) 
@Composable
fun CameraPreview(
    modifier: Modifier = Modifier,
    controller: LifecycleCameraController? = null,
    onFrame: ((Bitmap, Int, Float) -> Unit)? = null
) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val cameraExecutor = remember { Executors.newSingleThreadExecutor() }

    val cameraController = controller ?: remember { LifecycleCameraController(context) }

    // State to hold the focal length in PIXELS. 
    val focalLengthPxState = remember { mutableStateOf(0f) }

    // Periodically check/update focal length on the Main thread
    LaunchedEffect(cameraController) {
        while(true) {
            try {
                val info = cameraController.cameraInfo
                if (info != null) {
                    val camera2Info = Camera2CameraInfo.from(info)
                    
                    // 1. Get Focal Length (mm)
                    val focalLengths = camera2Info.getCameraCharacteristic(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)
                    val focalLengthMm = focalLengths?.firstOrNull() ?: 0f
                    
                    // 2. Get Sensor Size (mm)
                    val sensorSize: SizeF? = camera2Info.getCameraCharacteristic(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)
                    val sensorWidthMm = sensorSize?.width ?: 0f
                    
                    // 3. Get Image Width (pixels) - Assuming analysis width or preview width?
                    // Usually analysis runs on a specific resolution (e.g. 640x480 or similar).
                    // We can approximate or get it from the camera controller if accessible, 
                    // but usually it depends on the ImageAnalysis use case resolution.
                    // However, we can calculate fx_pixels if we assume the width of the captured frame (passed in onFrame)
                    // But here we are outside onFrame.
                    // Let's store the factors needed to calculate it inside onFrame.
                    
                    // Wait, we can pass focalLengthMm and sensorWidthMm to onFrame, and calculate there using bitmap.width.
                    // Or we can just calculate a "pixels per mm" factor if we knew the resolution.
                    // But resolution changes per frame (in onFrame).
                    // So let's store focalLengthMm and sensorWidthMm in the state or pass them.
                    
                    // Actually, let's just pass `focalLengthMm` and `sensorWidthMm` via the callback if possible, 
                    // or calculate a proxy here assuming a standard width? No, that's inaccurate.
                    
                    // Let's change the callback signature to accept (Bitmap, Int, Float, Float) -> Unit
                    // Or just calculate it inside the analyzer block where we have the bitmap width.
                    // But we need access to camera characteristics inside the analyzer? 
                    // The analyzer runs on background thread. accessing camera2Info might be safe?
                    // Yes, Camera2CameraInfo is thread safe.
                    
                    // To keep it simple, let's just update the state with the raw values we need.
                    // But the `onFrame` callback currently expects `Float` (focalLength).
                    // The prompt implies we should "get it from camera intrinsic api values".
                    // The `focalLengthPixels` depends on the image width: F_px = (F_mm / SensorWidth_mm) * ImageWidth_px
                    
                    // We can't calculate F_px here without ImageWidth_px.
                    // So we must do it in the analyzer.
                }
            } catch (e: Exception) {
                // Ignore errors
            }
            delay(2000) 
        }
    }

    if (onFrame != null) {
        LaunchedEffect(cameraController) {
            cameraController.setImageAnalysisAnalyzer(cameraExecutor) { imageProxy ->
                val bitmap = imageProxy.toBitmap()
                val rotationDegrees = imageProxy.imageInfo.rotationDegrees
                
                // Calculate Focal Length in Pixels
                var fxPixels = 0f
                try {
                    val info = cameraController.cameraInfo
                    if (info != null) {
                        val camera2Info = Camera2CameraInfo.from(info)
                        val focalLengths = camera2Info.getCameraCharacteristic(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)
                        val focalLengthMm = focalLengths?.firstOrNull() ?: 0f
                        
                        val sensorSize = camera2Info.getCameraCharacteristic(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)
                        val sensorWidthMm = sensorSize?.width ?: 0f
                        
                        if (sensorWidthMm > 0) {
                            val imageWidth = bitmap.width.toFloat()
                            fxPixels = (focalLengthMm / sensorWidthMm) * imageWidth
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }

                onFrame(bitmap, rotationDegrees, fxPixels)
                imageProxy.close()
            }
        }
    }
    
    if (controller == null) {
        LaunchedEffect(cameraController) {
            cameraController.setEnabledUseCases(LifecycleCameraController.IMAGE_ANALYSIS or LifecycleCameraController.IMAGE_CAPTURE or LifecycleCameraController.VIDEO_CAPTURE)
            cameraController.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            cameraController.bindToLifecycle(lifecycleOwner)
        }
    } else {
        LaunchedEffect(cameraController, lifecycleOwner) {
            cameraController.bindToLifecycle(lifecycleOwner)
        }
    }

    AndroidView(
        modifier = modifier,
        factory = { ctx ->
            PreviewView(ctx).apply {
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                this.controller = cameraController
            }
        },
        onRelease = {
             // Cleanup
        }
    )
}
