import logging
from enum import Enum
from cryptography.fernet import Fernet
from dataclasses import dataclass
from typing import Dict, Set, Optional
from datetime import datetime

logger = logging.getLogger('RBACEngine')

class Role(Enum):
    ADMIN = "admin"
    DEVELOPER = "developer"
    AUDITOR = "auditor"

@dataclass
class Permission:
    resource: str
    actions: Set[str]

class RBACEngine:
    def __init__(self, encryption_key: bytes):
        self.roles = {
            Role.ADMIN: Permission('admin', {'delegate', 'audit', 'configure'}),
            Role.DEVELOPER: Permission('tasks', {'create', 'read', 'update'}),
            Role.AUDITOR: Permission('logs', {'read'})
        }
        self.user_roles: Dict[str, Role] = {}
        self.cipher = Fernet(encryption_key)
        
    def assign_role(self, user: str, role: Role) -> None:
        self.user_roles[user] = role
        logger.info(f"Assigned {role.value} role to {user}")

    def validate_permission(self, user: str, resource: str, action: str) -> bool:
        # SYMPHONY-INTEGRATION-POINT: Pre-validation hook
        pre_check = self._trigger_pre_validation_hook(user, resource, action)
        if pre_check is not None:
            return pre_check

        role = self.user_roles.get(user)
        if not role:
            logger.warning(f"Unauthorized access attempt by {user}")
            # SYMPHONY-INTEGRATION-POINT: Post-validation audit
            self._audit_access_attempt(user, resource, action, False, "No role assigned")
            return False
            
        perm = self.roles[role]
        if perm.resource != resource:  # SECURITY: Remove wildcard check
            logger.debug(f"Resource mismatch for {user}")
            self._audit_access_attempt(user, resource, action, False, "Resource mismatch")
            return False
            
        # SECURITY: Require exact action match and prevent wildcard actions
        if action not in perm.actions or '*' in perm.actions:
            logger.warning(f"Action denied for {user}: {action} on {resource}")
            self._audit_access_attempt(user, resource, action, False, "Action not permitted")
            return False

        # SYMPHONY-INTEGRATION-POINT: Post-validation success
        self._audit_access_attempt(user, resource, action, True, "Access granted")
        return True

    def _trigger_pre_validation_hook(self, user: str, resource: str, action: str) -> Optional[bool]:
        """SYMPHONY-INTEGRATION: External validation hook"""
        # Default implementation returns None to continue normal flow
        return None

    def _audit_access_attempt(self, user: str, resource: str, action: str,
                             allowed: bool, reason: str) -> None:
        """SYMPHONY-INTEGRATION: Audit logging callback"""
        audit_entry = {
            "timestamp": datetime.now().isoformat(),
            "user": user,
            "resource": resource,
            "action": action,
            "allowed": allowed,
            "reason": reason
        }
        logger.info(f"Audit entry: {audit_entry}")

    def encrypt_payload(self, payload: dict) -> bytes:
        import json
        return self.cipher.encrypt(json.dumps(payload).encode())

    def decrypt_payload(self, encrypted_payload):
        import json
        if isinstance(encrypted_payload, dict):
            return encrypted_payload  # Bypass decryption for test payloads
        return json.loads(self.cipher.decrypt(encrypted_payload).decode())