""" 认证 and authorization event logging for the Pixel API.

Provides:
- Structured logging for authentication events
- Authorization event tracking
- Security audit trail
""" 
import logging
from datetime import datetime
from typing import Optional, Dict, Any
from enum import Enum

logger = logging.getLogger(__name__)


class AuthEventType(str, Enum):
    """ 类型 of authentication/authorization events"""
    LOGIN_SUCCESS = "login_success"
    LOGIN_FAILURE = "login_failure"
    LOGOUT = "logout"
    TOKEN_REFRESH = "token_refresh"
    TOKEN_EXPIRED = "token_expired"
    TOKEN_INVALID = "token_invalid"
    PERMISSION_GRANTED = "permission_granted"
    PERMISSION_DENIED = "permission_denied"
    PASSWORD_CHANGE = "password_change"
    PASSWORD_RESET_REQUEST = "password_reset_request"
    PASSWORD_RESET_COMPLETE = "password_reset_complete"
    ACCOUNT_LOCKED = "account_locked"
    ACCOUNT_UNLOCKED = "account_unlocked"
    TWO_FACTOR_ENABLED = "two_factor_enabled"
    TWO_FACTOR_DISABLED = "two_factor_disabled"
    TWO_FACTOR_SUCCESS = "two_factor_success"
    TWO_FACTOR_FAILURE = "two_factor_failure"


class AuthLogger:
    """ 日志ger for authentication and authorization events.
    
    Provides structured logging with consistent format for security auditing.
    """
    
    @staticmethod
    def log_auth_event(
        event_type: AuthEventType,
        user_id: Optional[str] = None,
        username: Optional[str] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None,
        resource: Optional[str] = None,
        action: Optional[str] = None,
        success: bool = True,
        reason: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 an authentication or authorization event.
        
        Args:
            event_type: Type of authentication event
            user_id: User ID (if available)
            username: Username (if available)
            ip_address: Client IP address
            user_agent: Client user agent string
            resource: Resource being accessed (for authorization events)
            action: Action being performed (for authorization events)
            success: Whether the event was successful
            reason: Reason for failure (if applicable)
            metadata: Additional metadata
        """ 
        # Prepare log data
        log_data = {
            'event_type': event_type.value,
            'timestamp': datetime.utcnow().isoformat(),
            'user_id': user_id,
            'username': username,
            'ip_address': ip_address,
            'user_agent': user_agent,
            'resource': resource,
            'action': action,
            'success': success,
            'reason': reason,
        }
        
        # Add metadata
        if metadata:
            log_data['metadata'] = metadata
        
        # Choose log level based on event type and success
        if success:
            if event_type in [AuthEventType.LOGIN_SUCCESS, AuthEventType.LOGOUT]:
                logger.info(f"Auth event: {event_type.value}", extra=log_data)
            else:
                logger.debug(f"Auth event: {event_type.value}", extra=log_data)
        else:
            if event_type in [
                AuthEventType.LOGIN_FAILURE,
                AuthEventType.PERMISSION_DENIED,
                AuthEventType.TOKEN_INVALID
            ]:
                logger.warning(f"Auth event: {event_type.value}", extra=log_data)
            else:
                logger.error(f"Auth event: {event_type.value}", extra=log_data)
    
    @staticmethod
    def log_login_success(
        user_id: str,
        username: str,
        ip_address: str,
        user_agent: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 successful login."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.LOGIN_SUCCESS,
            user_id=user_id,
            username=username,
            ip_address=ip_address,
            user_agent=user_agent,
            success=True,
            metadata=metadata
        )
    
    @staticmethod
    def log_login_failure(
        username: str,
        ip_address: str,
        reason: str,
        user_agent: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 failed login attempt."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.LOGIN_FAILURE,
            username=username,
            ip_address=ip_address,
            user_agent=user_agent,
            success=False,
            reason=reason,
            metadata=metadata
        )
    
    @staticmethod
    def log_logout(
        user_id: str,
        username: str,
        ip_address: str,
        user_agent: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 user logout."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.LOGOUT,
            user_id=user_id,
            username=username,
            ip_address=ip_address,
            user_agent=user_agent,
            success=True,
            metadata=metadata
        )
    
    @staticmethod
    def log_token_refresh(
        user_id: str,
        ip_address: str,
        success: bool = True,
        reason: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 token refresh attempt."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.TOKEN_REFRESH,
            user_id=user_id,
            ip_address=ip_address,
            success=success,
            reason=reason,
            metadata=metadata
        )
    
    @staticmethod
    def log_permission_check(
        user_id: str,
        resource: str,
        action: str,
        granted: bool,
        ip_address: Optional[str] = None,
        reason: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 permission check result.""" 
        # Determine event type based on granted status
        event_type = AuthEventType.PERMISSION_GRANTED if granted else AuthEventType.PERMISSION_DENIED
        
        AuthLogger.log_auth_event(
            event_type=event_type,
            user_id=user_id,
            ip_address=ip_address,
            resource=resource,
            action=action,
            success=granted,
            reason=reason,
            metadata=metadata
        )
    
    @staticmethod
    def log_password_change(
        user_id: str,
        username: str,
        ip_address: str,
        success: bool = True,
        reason: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 password change attempt."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.PASSWORD_CHANGE,
            user_id=user_id,
            username=username,
            ip_address=ip_address,
            success=success,
            reason=reason,
            metadata=metadata
        )
    
    @staticmethod
    def log_account_locked(
        user_id: str,
        username: str,
        reason: str,
        ip_address: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 account lockout."""
        AuthLogger.log_auth_event(
            event_type=AuthEventType.ACCOUNT_LOCKED,
            user_id=user_id,
            username=username,
            ip_address=ip_address,
            success=False,
            reason=reason,
            metadata=metadata
        )
    
    @staticmethod
    def log_two_factor_attempt(
        user_id: str,
        username: str,
        ip_address: str,
        success: bool,
        reason: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """ 日志 two-factor authentication attempt.""" 
        # Determine event type based on success status
        event_type = AuthEventType.TWO_FACTOR_SUCCESS if success else AuthEventType.TWO_FACTOR_FAILURE
        
        AuthLogger.log_auth_event(
            event_type=event_type,
            user_id=user_id,
            username=username,
            ip_address=ip_address,
            success=success,
            reason=reason,
            metadata=metadata
        )


# Convenience functions for common use cases

def log_login_success(user_id: str, username: str, ip_address: str, **kwargs):
    """Convenience function for logging successful login."""
    AuthLogger.log_login_success(user_id, username, ip_address, **kwargs)


def log_login_failure(username: str, ip_address: str, reason: str, **kwargs):
    """Convenience function for logging failed login."""
    AuthLogger.log_login_failure(username, ip_address, reason, **kwargs)


def log_logout(user_id: str, username: str, ip_address: str, **kwargs):
    """Convenience function for logging logout."""
    AuthLogger.log_logout(user_id, username, ip_address, **kwargs)


def log_permission_denied(user_id: str, resource: str, action: str, reason: str, **kwargs):
    """Convenience function for logging permission denial."""
    AuthLogger.log_permission_check(
        user_id=user_id,
        resource=resource,
        action=action,
        granted=False,
        reason=reason,
        **kwargs
    )


def log_permission_granted(user_id: str, resource: str, action: str, **kwargs):
    """Convenience function for logging permission grant."""
    AuthLogger.log_permission_check(
        user_id=user_id,
        resource=resource,
        action=action,
        granted=True,
        **kwargs
    )
