#include "permission_gate.h"
#include "lua_sandbox.h"

#include <lua.hpp>
#include <algorithm>

namespace mosis {

//=============================================================================
// PERMISSION DATABASE
//=============================================================================

static const std::unordered_map<std::string, PermissionInfo> PERMISSIONS = {
    // Normal permissions (auto-granted when declared)
    {"internet",         {PermissionCategory::Normal, "Access the internet"}},
    {"vibrate",          {PermissionCategory::Normal, "Vibrate the device"}},
    {"wake_lock",        {PermissionCategory::Normal, "Keep device awake"}},
    {"notifications",    {PermissionCategory::Normal, "Show notifications"}},
    {"alarms",           {PermissionCategory::Normal, "Set alarms"}},
    {"nfc",              {PermissionCategory::Normal, "Use NFC"}},

    // Dangerous permissions (require user consent)
    {"camera",           {PermissionCategory::Dangerous, "Access the camera"}},
    {"microphone",       {PermissionCategory::Dangerous, "Record audio"}},
    {"location.fine",    {PermissionCategory::Dangerous, "Access precise location"}},
    {"location.coarse",  {PermissionCategory::Dangerous, "Access approximate location"}},
    {"contacts.read",    {PermissionCategory::Dangerous, "Read contacts"}},
    {"contacts.write",   {PermissionCategory::Dangerous, "Modify contacts"}},
    {"storage.external", {PermissionCategory::Dangerous, "Access external storage"}},
    {"storage.shared",   {PermissionCategory::Dangerous, "Access shared storage"}},
    {"sensors.motion",   {PermissionCategory::Dangerous, "Access motion sensors"}},
    {"bluetooth",        {PermissionCategory::Dangerous, "Use Bluetooth"}},
    {"bluetooth.scan",   {PermissionCategory::Dangerous, "Scan for Bluetooth devices"}},
    {"calendar.read",    {PermissionCategory::Dangerous, "Read calendar"}},
    {"calendar.write",   {PermissionCategory::Dangerous, "Modify calendar"}},
    {"phone.call",       {PermissionCategory::Dangerous, "Make phone calls"}},
    {"phone.read_state", {PermissionCategory::Dangerous, "Read phone state"}},
    {"sms.read",         {PermissionCategory::Dangerous, "Read SMS messages"}},
    {"sms.send",         {PermissionCategory::Dangerous, "Send SMS messages"}},

    // Signature permissions (system apps only)
    {"system.settings",  {PermissionCategory::Signature, "Modify system settings"}},
    {"system.install",   {PermissionCategory::Signature, "Install apps"}},
    {"system.uninstall", {PermissionCategory::Signature, "Uninstall apps"}},
    {"system.admin",     {PermissionCategory::Signature, "Device administrator"}},
    {"system.overlay",   {PermissionCategory::Signature, "Display over other apps"}},
    {"system.wallpaper", {PermissionCategory::Signature, "Set wallpaper"}},
};

//=============================================================================
// CONSTRUCTOR
//=============================================================================

PermissionGate::PermissionGate(const SandboxContext& context)
    : m_context(context)
    , m_last_gesture(std::chrono::steady_clock::time_point::min())
{
}

//=============================================================================
// PERMISSION INFO
//=============================================================================

PermissionCategory PermissionGate::GetCategory(const std::string& permission) {
    auto it = PERMISSIONS.find(permission);
    if (it != PERMISSIONS.end()) {
        return it->second.category;
    }
    // Unknown permissions default to Dangerous for safety
    return PermissionCategory::Dangerous;
}

const PermissionInfo* PermissionGate::GetPermissionInfo(const std::string& permission) {
    auto it = PERMISSIONS.find(permission);
    if (it != PERMISSIONS.end()) {
        return &it->second;
    }
    return nullptr;
}

//=============================================================================
// PERMISSION CHECKING
//=============================================================================

bool PermissionGate::HasPermission(const std::string& permission) const {
    auto category = GetCategory(permission);

    switch (category) {
        case PermissionCategory::Normal:
            return CheckNormalPermission(permission);
        case PermissionCategory::Dangerous:
            return CheckDangerousPermission(permission);
        case PermissionCategory::Signature:
            return CheckSignaturePermission(permission);
    }
    return false;
}

bool PermissionGate::Check(lua_State* L, const std::string& permission) {
    if (!HasPermission(permission)) {
        luaL_error(L, "permission denied: %s", permission.c_str());
        return false;
    }
    return true;
}

bool PermissionGate::IsDeclared(const std::string& permission) const {
    const auto& declared = m_context.permissions;
    return std::find(declared.begin(), declared.end(), permission) != declared.end();
}

bool PermissionGate::CheckNormalPermission(const std::string& permission) const {
    // Normal permissions are auto-granted if declared in manifest
    return IsDeclared(permission);
}

bool PermissionGate::CheckDangerousPermission(const std::string& permission) const {
    // Must be declared in manifest
    if (!IsDeclared(permission)) {
        return false;
    }

    // System apps get dangerous permissions automatically
    if (m_context.is_system_app) {
        return true;
    }

    // Regular apps need runtime grant
    return m_runtime_grants.count(permission) > 0;
}

bool PermissionGate::CheckSignaturePermission(const std::string& permission) const {
    // Only system apps get signature permissions
    if (!m_context.is_system_app) {
        return false;
    }

    // Must still be declared
    return IsDeclared(permission);
}

//=============================================================================
// USER GESTURE TRACKING
//=============================================================================

void PermissionGate::RecordUserGesture() {
    m_last_gesture = std::chrono::steady_clock::now();
}

bool PermissionGate::HasRecentUserGesture(int ms) const {
    // If no gesture has been recorded, return false
    if (m_last_gesture == std::chrono::steady_clock::time_point::min()) {
        return false;
    }

    auto now = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_gesture);
    return elapsed.count() < ms;
}

//=============================================================================
// RUNTIME GRANTS
//=============================================================================

void PermissionGate::GrantPermission(const std::string& permission) {
    // Can only grant dangerous permissions
    auto category = GetCategory(permission);
    if (category == PermissionCategory::Dangerous) {
        m_runtime_grants.insert(permission);
    }
}

void PermissionGate::RevokePermission(const std::string& permission) {
    m_runtime_grants.erase(permission);
}

//=============================================================================
// QUERIES
//=============================================================================

const std::vector<std::string>& PermissionGate::GetDeclaredPermissions() const {
    return m_context.permissions;
}

std::vector<std::string> PermissionGate::GetGrantedPermissions() const {
    std::vector<std::string> granted;

    for (const auto& perm : m_context.permissions) {
        if (HasPermission(perm)) {
            granted.push_back(perm);
        }
    }

    return granted;
}

} // namespace mosis
