package com.nexlab.openclaw.node.service

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import com.nexlab.openclaw.node.domain.model.PermissionAction
import com.nexlab.openclaw.node.domain.model.PermissionDecision
import com.nexlab.openclaw.node.domain.model.PermissionResult
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

private val Context.permissionDataStore: DataStore<Preferences> by preferencesDataStore(name = "permissions")

@Singleton
class PermissionManager @Inject constructor(
    @ApplicationContext private val context: Context
) {
    companion object {
        // Keys for remembering decisions
        private fun rememberKey(actionId: String) = booleanPreferencesKey("remember_${actionId}")
        private fun allowedKey(actionId: String) = booleanPreferencesKey("allowed_${actionId}")
    }

    // Default allowlist - actions that don't need confirmation
    private val defaultAllowlist = setOf(
        "screenshot",
        "touch", 
        "launch_app",
        "shell",
        "notifications"
    )

    // High sensitivity actions that always need confirmation
    private val highSensitivityActions = setOf(
        "camera",
        "microphone",
        "location",
        "contacts",
        "phone",
        "sms"
    )

    /**
     * Check if an action is allowed
     * Returns the appropriate PermissionResult
     */
    suspend fun checkPermission(action: PermissionAction): PermissionResult {
        // Check if user has permanently remembered a decision
        val remembered = isDecisionRemembered(action.id)
        if (remembered) {
            val allowed = isAllowed(action.id)
            return if (allowed) PermissionResult.Allowed else PermissionResult.Denied
        }

        // Check system permissions for sensitive actions
        val systemResult = checkSystemPermission(action)
        if (systemResult != null) {
            return systemResult
        }

        // Check sensitivity level
        return when (action.sensitivity) {
            PermissionAction.Sensitivity.LOW -> {
                // Low sensitivity - auto-allow
                PermissionResult.Allowed
            }
            PermissionAction.Sensitivity.MEDIUM -> {
                // Medium sensitivity - check allowlist
                if (isInAllowlist(action.id)) {
                    PermissionResult.Allowed
                } else {
                    PermissionResult.PendingConfirmation
                }
            }
            PermissionAction.Sensitivity.HIGH -> {
                // High sensitivity - always confirm
                PermissionResult.PendingConfirmation
            }
        }
    }

    /**
     * Process a user's decision on a permission
     */
    suspend fun decide(
        action: PermissionAction,
        allowed: Boolean,
        rememberChoice: Boolean
    ) {
        // Store the decision
        context.permissionDataStore.edit { preferences ->
            preferences[allowedKey(action.id)] = allowed
            if (rememberChoice) {
                preferences[rememberKey(action.id)] = true
            }
        }
    }

    /**
     * Clear a remembered decision
     */
    suspend fun clearDecision(actionId: String) {
        context.permissionDataStore.edit { preferences ->
            preferences.remove(rememberKey(actionId))
            preferences.remove(allowedKey(actionId))
        }
    }

    /**
     * Clear all remembered decisions
     */
    suspend fun clearAllDecisions() {
        context.permissionDataStore.edit { preferences ->
            preferences.clear()
        }
    }

    /**
     * Add action to allowlist (no confirmation needed)
     */
    suspend fun addToAllowlist(actionId: String) {
        context.permissionDataStore.edit { preferences ->
            preferences[booleanPreferencesKey("allowlist_$actionId")] = true
        }
    }

    /**
     * Remove action from allowlist
     */
    suspend fun removeFromAllowlist(actionId: String) {
        context.permissionDataStore.edit { preferences ->
            preferences.remove(booleanPreferencesKey("allowlist_$actionId"))
        }
    }

    /**
     * Get all actions in allowlist
     */
    fun getAllowlist(): Flow<Set<String>> = context.permissionDataStore.data.map { preferences ->
        preferences.asMap()
            .filter { (key, value) -> 
                key.name.startsWith("allowlist_") && value == true
            }
            .map { it.key.name.removePrefix("allowlist_") }
            .toSet()
    }

    /**
     * Get all remembered decisions
     */
    fun getAllDecisions(): Flow<Map<String, PermissionDecision>> = context.permissionDataStore.data.map { preferences ->
        preferences.asMap()
            .filter { it.key.name.startsWith("allowed_") }
            .mapNotNull { (key, value) ->
                val actionId = key.name.removePrefix("allowed_")
                val rememberKey = rememberKey(actionId)
                val remembered = preferences[rememberKey] ?: false
                val allowed = value as? Boolean ?: return@mapNotNull null
                
                actionId to PermissionDecision(
                    actionId = actionId,
                    allowed = allowed,
                    rememberChoice = remembered
                )
            }
            .toMap()
    }

    // Private helpers

    private suspend fun isDecisionRemembered(actionId: String): Boolean {
        return context.permissionDataStore.data.first()[rememberKey(actionId)] ?: false
    }

    private suspend fun isAllowed(actionId: String): Boolean {
        return context.permissionDataStore.data.first()[allowedKey(actionId)] ?: false
    }

    private suspend fun isInAllowlist(actionId: String): Boolean {
        return context.permissionDataStore.data.first()[booleanPreferencesKey("allowlist_$actionId")] 
            ?: defaultAllowlist.contains(actionId)
    }

    private fun checkSystemPermission(action: PermissionAction): PermissionResult? {
        // Check Android runtime permissions
        val permission = when (action.id) {
            "camera" -> Manifest.permission.CAMERA
            "microphone" -> Manifest.permission.RECORD_AUDIO
            "location" -> Manifest.permission.ACCESS_FINE_LOCATION
            "contacts" -> Manifest.permission.READ_CONTACTS
            "phone" -> Manifest.permission.READ_PHONE_STATE
            "sms" -> Manifest.permission.READ_SMS
            "storage" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                Manifest.permission.READ_MEDIA_IMAGES
            } else {
                Manifest.permission.READ_EXTERNAL_STORAGE
            }
            else -> null
        }

        if (permission != null) {
            val granted = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
            return if (!granted) {
                PermissionResult.NeedsSystemPermission(action)
            } else {
                null // System permission granted, continue with app-level check
            }
        }

        return null
    }
}

/**
 * Extension to get all permission decisions as a list
 */
suspend fun PermissionManager.getPermissionStatus(): Map<String, PermissionDecision> {
    return getAllDecisions().first()
}
