package com.tt.honeyDue.platform

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.interop.LocalUIViewController
import kotlinx.cinterop.*
import platform.Foundation.*
import platform.PhotosUI.*
import platform.UIKit.*
import platform.darwin.NSObject
import platform.posix.memcpy

@OptIn(ExperimentalForeignApi::class)
@Composable
actual fun rememberImagePicker(
    onImagesPicked: (List<ImageData>) -> Unit
): () -> Unit {
    val viewController = LocalUIViewController.current

    val pickerDelegate = remember {
        object : NSObject(), PHPickerViewControllerDelegateProtocol {
            override fun picker(
                picker: PHPickerViewController,
                didFinishPicking: List<*>
            ) {
                picker.dismissViewControllerAnimated(true, null)

                val results = didFinishPicking as List<PHPickerResult>
                if (results.isEmpty()) {
                    return
                }

                val images = mutableListOf<ImageData>()
                var processedCount = 0

                results.forEach { result ->
                    val itemProvider = result.itemProvider

                    // Check if the item has an image using UTType
                    if (itemProvider.hasItemConformingToTypeIdentifier("public.image")) {
                        itemProvider.loadFileRepresentationForTypeIdentifier(
                            typeIdentifier = "public.image",
                            completionHandler = { url, error ->
                                if (error == null && url != null) {
                                    // Read the image data from the file URL
                                    val imageData = NSData.dataWithContentsOfURL(url)
                                    if (imageData != null) {
                                        // Convert to UIImage and then to JPEG for consistent format
                                        val image = UIImage.imageWithData(imageData)
                                        if (image != null) {
                                            val jpegData = UIImageJPEGRepresentation(image, 0.8)
                                            if (jpegData != null) {
                                                val bytes = jpegData.toByteArray()
                                                val fileName = "image_${NSDate().timeIntervalSince1970.toLong()}_${processedCount}.jpg"
                                                synchronized(images) {
                                                    images.add(ImageData(bytes, fileName))
                                                }
                                            }
                                        }
                                    }
                                }

                                processedCount++

                                // When all images are processed, call the callback
                                if (processedCount == results.size) {
                                    if (images.isNotEmpty()) {
                                        onImagesPicked(images.toList())
                                    }
                                }
                            }
                        )
                    } else {
                        processedCount++
                    }
                }
            }
        }
    }

    return {
        val config = PHPickerConfiguration().apply {
            setSelectionLimit(5)
            setFilter(PHPickerFilter.imagesFilter())
        }

        val picker = PHPickerViewController(config).apply {
            setDelegate(pickerDelegate)
        }

        viewController.presentViewController(picker, animated = true, completion = null)
    }
}

@OptIn(ExperimentalForeignApi::class)
private fun NSData.toByteArray(): ByteArray {
    return ByteArray(length.toInt()).apply {
        usePinned {
            memcpy(it.addressOf(0), bytes, length)
        }
    }
}

@OptIn(ExperimentalForeignApi::class)
@Composable
actual fun rememberCameraPicker(
    onImageCaptured: (ImageData) -> Unit
): () -> Unit {
    val viewController = LocalUIViewController.current

    val cameraDelegate = remember {
        object : NSObject(), UIImagePickerControllerDelegateProtocol, UINavigationControllerDelegateProtocol {
            override fun imagePickerController(
                picker: UIImagePickerController,
                didFinishPickingMediaWithInfo: Map<Any?, *>
            ) {
                picker.dismissViewControllerAnimated(true, null)

                val image = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as? UIImage
                if (image != null) {
                    // Convert to JPEG
                    val jpegData = UIImageJPEGRepresentation(image, 0.8)
                    if (jpegData != null) {
                        val bytes = jpegData.toByteArray()
                        val fileName = "camera_${NSDate().timeIntervalSince1970.toLong()}.jpg"
                        onImageCaptured(ImageData(bytes, fileName))
                    }
                }
            }

            override fun imagePickerControllerDidCancel(picker: UIImagePickerController) {
                picker.dismissViewControllerAnimated(true, null)
            }
        }
    }

    return {
        // Check if camera is available
        if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.UIImagePickerControllerSourceTypeCamera)) {
            val picker = UIImagePickerController().apply {
                setSourceType(UIImagePickerControllerSourceType.UIImagePickerControllerSourceTypeCamera)
                setDelegate(cameraDelegate)
                setCameraCaptureMode(UIImagePickerControllerCameraCaptureMode.UIImagePickerControllerCameraCaptureModePhoto)
            }

            viewController.presentViewController(picker, animated = true, completion = null)
        }
    }
}

@Suppress("UNCHECKED_CAST")
private fun <T : Any> synchronized(lock: Any, block: () -> T): T {
    return block()
}
