package cl.homelogic.platform.common.permissions.composables

import androidx.compose.foundation.layout.LayoutScopeMarker
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.remember
import cl.homelogic.platform.common.permissions.PermissionStatus
import cl.homelogic.platform.common.permissions.PermissionType
import cl.homelogic.platform.common.permissions.PermissionType.Companion.toMokoPermission
import cl.homelogic.platform.common.permissions.toPermissionStatus
import dev.icerock.moko.permissions.DeniedAlwaysException
import dev.icerock.moko.permissions.DeniedException
import dev.icerock.moko.permissions.PermissionsController
import dev.icerock.moko.permissions.RequestCanceledException
import dev.icerock.moko.permissions.compose.PermissionsControllerFactory
import dev.icerock.moko.permissions.compose.rememberPermissionsControllerFactory

@Composable
fun PermissionSystem(
    content: @Composable PermissionsScope.() -> Unit,
) {
    val factory: PermissionsControllerFactory = rememberPermissionsControllerFactory()
    val controller: PermissionsController = remember(factory) {
        factory.createPermissionsController()
    }

    PermissionsScopeInstance(controller).content()
}

@LayoutScopeMarker
@Immutable
interface PermissionsScope {
    suspend fun requestPermission(permission: PermissionType): PermissionStatus

    suspend fun isPermissionGranted(permission: PermissionType): Boolean

    suspend fun getPermissionState(permission: PermissionType): PermissionStatus

    fun openAppSettings()
}

internal class PermissionsScopeInstance(
    private val permissionsController: PermissionsController,
) : PermissionsScope {
    override suspend fun requestPermission(permission: PermissionType): PermissionStatus {
        try {
            permissionsController.providePermission(permission.toMokoPermission())
            return PermissionStatus.Granted
        } catch (deniedAlways: DeniedAlwaysException) {
            return PermissionStatus.Denied
        } catch (denied: DeniedException) {
            return PermissionStatus.Denied
        } catch (canceled: RequestCanceledException) {
            return PermissionStatus.NotGranted
        } catch (exception: Exception) {
            return PermissionStatus.NotGranted
        }
    }

    override suspend fun isPermissionGranted(permission: PermissionType): Boolean =
        permissionsController.isPermissionGranted(
            permission.toMokoPermission(),
        )

    override suspend fun getPermissionState(permission: PermissionType): PermissionStatus =
        permissionsController
            .getPermissionState(
                permission.toMokoPermission(),
            ).toPermissionStatus()

    override fun openAppSettings() {
        permissionsController.openAppSettings()
    }
}
