package com.performancecoachlab.posedetection.custom

import androidx.compose.runtime.Composable
import kotlinx.cinterop.ExperimentalForeignApi
import platform.CoreML.MLModel
import platform.Foundation.NSBundle
import platform.Foundation.NSURL
import platform.Vision.VNCoreMLModel

@Composable
actual fun initialiseObjectModel(modelPath: ModelPath): ObjectModel {
    return createObjectDetector(modelPath.iosModelPath)
}

@OptIn(ExperimentalForeignApi::class)
fun createObjectDetector(model: String?): ObjectModel {
    if (model == null) {
        return ObjectModel(null, 0, 0)
    }
    val path = NSBundle.mainBundle.pathForResource(model, "mlmodelc")
    val url = path?.let { NSURL.fileURLWithPath(it) }
    val mlModel = url?.let { MLModel.modelWithContentsOfURL(it, null) }
    val vnModel = mlModel?.let { VNCoreMLModel.modelForMLModel(it, null) }
    val (w, h) = inferInputSizeFromName(model)
    return ObjectModel(vnModel, w, h)
}

// Infer the model's letterbox input size from the filename suffix.
// Matches the `_<W>x<H>` convention used by the rect exports (e.g.
// `yolo26n_v11_rect_512x384`). Models without this suffix get (0, 0),
// which disables letterboxing and preserves prior Vision-default behavior.
private val INPUT_SIZE_SUFFIX = Regex("_(\\d+)x(\\d+)$")

internal fun inferInputSizeFromName(name: String): Pair<Int, Int> {
    INPUT_SIZE_SUFFIX.find(name)?.let { m ->
        val w = m.groupValues[1].toIntOrNull() ?: return 0 to 0
        val h = m.groupValues[2].toIntOrNull() ?: return 0 to 0
        return w to h
    }
    return 0 to 0
}

actual class ObjectModel(
    private val model: VNCoreMLModel?,
    val inputWidth: Int,
    val inputHeight: Int,
) {
    fun getModel(): VNCoreMLModel? = model
}

@Composable
internal actual fun platformRememberObjectModel(modelPath: ModelPath): ObjectModel {
    // iOS: create once for this composition; avoids global caching issues
    return initialiseObjectModel(modelPath)
}