"""
Enhanced methods for CustomUser model to support both legacy and granular permission systems
"""
from django.conf import settings
from django.core.cache import cache
from django.utils import timezone
from typing import Dict, List, Optional, Any, Tuple
import logging

logger = logging.getLogger(__name__)


class EnhancedUserPermissionMethods:
    """
    Mixin class that provides enhanced permission methods for CustomUser
    """
    
    def has_page_permission(self, page_name: str, action_code: str) -> bool:
        """
        Check if user has a specific page permission using the granular system
        
        Args:
            page_name: Name of the page (e.g., 'loans', 'clients')
            action_code: Action code (e.g., 'loans_create_application')
            
        Returns:
            bool: True if user has permission, False otherwise
        """
        # Admin users have all permissions
        if self.role == 'admin':
            return True
        
        try:
            from users.permission_compatibility import permission_compatibility
            return permission_compatibility.has_page_permission(self, page_name, action_code)
        except Exception as e:
            logger.warning(f"Error checking page permission: {e}")
            # Fall back to legacy system
            return self._check_legacy_page_permission(page_name, action_code)
    
    def get_page_permissions(self, page_name: str) -> Dict[str, bool]:
        """
        Get all permissions for a specific page
        
        Args:
            page_name: Name of the page
            
        Returns:
            Dict mapping action codes to permission status
        """
        if self.role == 'admin':
            # Admin has all permissions - get all available actions for the page
            try:
                from users.enhanced_permissions_models import PagePermission
                actions = PagePermission.objects.filter(
                    page_name=page_name,
                    is_active=True
                ).values_list('action_code', flat=True)
                return {action: True for action in actions}
            except ImportError:
                return {}
        
        try:
            from users.services import PagePermissionManager
            permission_manager = PagePermissionManager()
            return permission_manager.get_page_permissions(self, page_name)
        except Exception as e:
            logger.warning(f"Error getting page permissions: {e}")
            # Fall back to legacy system
            return self._get_legacy_page_permissions(page_name)
    
    def get_effective_permissions_enhanced(self) -> Dict[str, Any]:
        """
        Get effective permissions with source information using enhanced granular system
        
        Returns:
            Dictionary with permission information including source tracking
        """
        if self.role == 'admin':
            return self._get_admin_permissions()
        
        try:
            from users.services import PagePermissionManager
            from users.enhanced_permissions_models import PagePermission
            
            permission_manager = PagePermissionManager()
            permissions = {}
            
            # Get all available pages
            pages = PagePermission.objects.filter(is_active=True).values_list('page_name', flat=True).distinct()
            
            for page_name in pages:
                page_permissions = {}
                page_actions = PagePermission.objects.filter(
                    page_name=page_name,
                    is_active=True
                )
                
                for page_permission in page_actions:
                    # Check if user has this permission
                    has_permission = permission_manager.check_action_permission(
                        self, page_name, page_permission.action_code
                    )
                    
                    # Get source information
                    source_info = self._get_permission_source(page_permission)
                    
                    page_permissions[page_permission.action_code] = {
                        'allowed': has_permission,
                        'source': source_info['source'],
                        'granted_by': source_info.get('granted_by'),
                        'reason': source_info.get('reason'),
                        'expires_at': source_info.get('expires_at'),
                        'is_critical': page_permission.is_critical,
                        'category': page_permission.category,
                        'description': page_permission.description,
                    }
                
                permissions[page_name] = page_permissions
            
            return {
                'permissions': permissions,
                'system': 'granular',
                'timestamp': timezone.now().isoformat(),
                'user_role': self.role,
                'user_id': str(self.id)
            }
            
        except Exception as e:
            logger.warning(f"Error getting enhanced permissions: {e}")
            # Fall back to legacy system with enhanced format
            return self._get_legacy_permissions_enhanced()
    
    def get_available_page_actions(self, page_name: str) -> List[str]:
        """
        Get list of actions user can perform on a specific page
        
        Args:
            page_name: Name of the page
            
        Returns:
            List of action codes user can perform
        """
        try:
            from users.permission_compatibility import permission_compatibility
            return permission_compatibility.get_available_actions(self, page_name)
        except Exception as e:
            logger.warning(f"Error getting available actions: {e}")
            return []
    
    def can_override_permission(self, page_permission) -> bool:
        """
        Check if this user's permissions can be overridden for a specific page permission
        
        Args:
            page_permission: PagePermission instance
            
        Returns:
            bool: True if permission can be overridden
        """
        try:
            from users.enhanced_permissions_models import RolePermissionTemplate
            
            # Check if role template allows overrides
            template = RolePermissionTemplate.objects.filter(
                role=self.role,
                page_permission=page_permission
            ).first()
            
            if template:
                return template.can_override
            
            # Default to allowing overrides if no template exists
            return True
            
        except Exception:
            # Default to allowing overrides if we can't determine
            return True
    
    def get_permission_source(self, page_name: str, action_code: str) -> Dict[str, Any]:
        """
        Get the source of a specific permission (role template vs custom override)
        
        Args:
            page_name: Name of the page
            action_code: Action code
            
        Returns:
            Dict with source information
        """
        try:
            from users.enhanced_permissions_models import PagePermission
            
            page_permission = PagePermission.objects.get(
                page_name=page_name,
                action_code=action_code
            )
            
            return self._get_permission_source(page_permission)
            
        except Exception as e:
            logger.warning(f"Error getting permission source: {e}")
            return {'source': 'unknown'}
    
    def invalidate_permission_cache(self):
        """Invalidate cached permissions for this user"""
        try:
            from users.permission_compatibility import permission_compatibility
            permission_compatibility.invalidate_user_cache(self)
        except Exception as e:
            logger.warning(f"Error invalidating permission cache: {e}")
    
    def _check_legacy_page_permission(self, page_name: str, action_code: str) -> bool:
        """Check page permission using legacy system"""
        # Convert page permission to legacy module/action format
        if '_' in action_code:
            parts = action_code.split('_', 1)
            module = parts[0]
            action = parts[1] if len(parts) > 1 else 'access'
        else:
            module = page_name
            action = action_code
        
        return self.has_permission(module, action)
    
    def _get_legacy_page_permissions(self, page_name: str) -> Dict[str, bool]:
        """Get page permissions using legacy system"""
        permissions = {}
        
        # Get modules that correspond to this page
        modules = self._get_modules_for_page(page_name)
        
        from users.models import RolePermission
        
        for module in modules:
            # Get all possible actions for this module
            actions = RolePermission.objects.filter(
                module=module
            ).values_list('action', flat=True).distinct()
            
            for action in actions:
                action_code = f"{module}_{action}"
                permissions[action_code] = self.has_permission(module, action)
        
        return permissions
    
    def _get_admin_permissions(self) -> Dict[str, Any]:
        """Get all permissions for admin user"""
        try:
            from users.enhanced_permissions_models import PagePermission
            
            permissions = {}
            pages = PagePermission.objects.filter(is_active=True).values_list('page_name', flat=True).distinct()
            
            for page_name in pages:
                page_permissions = {}
                page_actions = PagePermission.objects.filter(
                    page_name=page_name,
                    is_active=True
                )
                
                for page_permission in page_actions:
                    page_permissions[page_permission.action_code] = {
                        'allowed': True,
                        'source': 'admin_role',
                        'granted_by': None,
                        'reason': 'Admin role has all permissions',
                        'expires_at': None,
                        'is_critical': page_permission.is_critical,
                        'category': page_permission.category,
                        'description': page_permission.description,
                    }
                
                permissions[page_name] = page_permissions
            
            return {
                'permissions': permissions,
                'system': 'granular',
                'timestamp': timezone.now().isoformat(),
                'user_role': 'admin',
                'user_id': str(self.id)
            }
            
        except ImportError:
            # Fall back to legacy system
            return self._get_legacy_permissions_enhanced()
    
    def _get_permission_source(self, page_permission) -> Dict[str, Any]:
        """Get source information for a specific page permission"""
        try:
            from users.enhanced_permissions_models import UserPagePermission, RolePermissionTemplate
            
            # Check for custom user permission first
            user_perm = UserPagePermission.objects.filter(
                user=self,
                page_permission=page_permission
            ).first()
            
            if user_perm and not user_perm.is_expired():
                return {
                    'source': 'custom',
                    'granted_by': user_perm.granted_by.get_full_name() if user_perm.granted_by else None,
                    'reason': user_perm.reason,
                    'expires_at': user_perm.expires_at,
                }
            
            # Check role template
            template = RolePermissionTemplate.objects.filter(
                role=self.role,
                page_permission=page_permission
            ).first()
            
            if template:
                return {
                    'source': 'role_template',
                    'granted_by': template.created_by.get_full_name() if template.created_by else None,
                    'reason': f'Default permission for {self.get_role_display()} role',
                    'expires_at': None,
                }
            
            return {
                'source': 'default',
                'granted_by': None,
                'reason': 'Default system permission',
                'expires_at': None,
            }
            
        except Exception as e:
            logger.warning(f"Error getting permission source: {e}")
            return {'source': 'unknown'}
    
    def _get_legacy_permissions_enhanced(self) -> Dict[str, Any]:
        """Get legacy permissions in enhanced format"""
        legacy_permissions = self.get_effective_permissions()
        
        # Convert to enhanced format
        enhanced_permissions = {}
        
        for module, actions in legacy_permissions.items():
            if isinstance(actions, dict):
                page_name = self._convert_module_to_page(module)
                if page_name not in enhanced_permissions:
                    enhanced_permissions[page_name] = {}
                
                for action, perm_info in actions.items():
                    action_code = f"{module}_{action}"
                    if isinstance(perm_info, dict):
                        enhanced_permissions[page_name][action_code] = {
                            'allowed': perm_info.get('allowed', False),
                            'source': perm_info.get('source', 'legacy'),
                            'granted_by': perm_info.get('granted_by'),
                            'reason': perm_info.get('reason'),
                            'expires_at': perm_info.get('expires_at'),
                            'is_critical': False,
                            'category': 'manage',
                            'description': f'Legacy permission for {module} {action}',
                        }
                    else:
                        enhanced_permissions[page_name][action_code] = {
                            'allowed': bool(perm_info),
                            'source': 'legacy',
                            'granted_by': None,
                            'reason': 'Legacy permission',
                            'expires_at': None,
                            'is_critical': False,
                            'category': 'manage',
                            'description': f'Legacy permission for {module} {action}',
                        }
        
        return {
            'permissions': enhanced_permissions,
            'system': 'legacy',
            'timestamp': timezone.now().isoformat(),
            'user_role': self.role,
            'user_id': str(self.id)
        }
    
    def _get_modules_for_page(self, page_name: str) -> List[str]:
        """Get legacy modules that correspond to a page"""
        page_to_modules = {
            'dashboard': [
                'dashboard', 'dashboard_overview', 'dashboard_metrics', 
                'dashboard_charts', 'dashboard_recent_activities', 'dashboard_quick_actions',
                'dashboard_loan_summary', 'dashboard_collection_summary', 
                'dashboard_branch_performance', 'dashboard_alerts'
            ],
            'clients': [
                'clients', 'clients_view_list', 'clients_search_filter',
                'clients_create_new', 'clients_edit_profile', 'clients_delete_client',
                'clients_view_details', 'clients_loan_history', 'clients_payment_history',
                'clients_kyc_documents', 'clients_assign_portfolio', 'clients_registration_fee',
                'clients_status_change', 'clients_export_data', 'clients_bulk_actions'
            ],
            'loans': [
                'loans', 'loans_view_list', 'loans_search_filter',
                'loans_create_application', 'loans_edit_application', 'loans_delete_loan',
                'loans_approve_application', 'loans_reject_application', 'loans_disburse_funds',
                'loans_view_details', 'loans_amortization_schedule', 'loans_rollover_loan',
                'loans_calculate_interest', 'loans_generate_receipt', 'loans_modify_terms',
                'loans_close_loan', 'loans_export_data'
            ],
            'repayments': ['repayments'],
            'portfolio': ['portfolio'],
            'reports': ['reports_statements'],
            'documents': ['documents', 'customer_documents'],
            'receipts': ['payment_receipts'],
            'notifications': ['notifications'],
            'settings': ['settings', 'branch_settings', 'system_settings'],
        }
        
        return page_to_modules.get(page_name, [page_name])
    
    def _convert_module_to_page(self, module: str) -> str:
        """Convert legacy module name to page name"""
        page_mapping = {
            'dashboard': 'dashboard',
            'dashboard_overview': 'dashboard',
            'dashboard_metrics': 'dashboard',
            'dashboard_charts': 'dashboard',
            'dashboard_recent_activities': 'dashboard',
            'dashboard_quick_actions': 'dashboard',
            'dashboard_loan_summary': 'dashboard',
            'dashboard_collection_summary': 'dashboard',
            'dashboard_branch_performance': 'dashboard',
            'dashboard_alerts': 'dashboard',
            
            'clients': 'clients',
            'clients_view_list': 'clients',
            'clients_search_filter': 'clients',
            'clients_create_new': 'clients',
            'clients_edit_profile': 'clients',
            'clients_delete_client': 'clients',
            'clients_view_details': 'clients',
            'clients_loan_history': 'clients',
            'clients_payment_history': 'clients',
            'clients_kyc_documents': 'clients',
            'clients_assign_portfolio': 'clients',
            'clients_registration_fee': 'clients',
            'clients_status_change': 'clients',
            'clients_export_data': 'clients',
            'clients_bulk_actions': 'clients',
            
            'loans': 'loans',
            'loans_view_list': 'loans',
            'loans_search_filter': 'loans',
            'loans_create_application': 'loans',
            'loans_edit_application': 'loans',
            'loans_delete_loan': 'loans',
            'loans_approve_application': 'loans',
            'loans_reject_application': 'loans',
            'loans_disburse_funds': 'loans',
            'loans_view_details': 'loans',
            'loans_amortization_schedule': 'loans',
            'loans_rollover_loan': 'loans',
            'loans_calculate_interest': 'loans',
            'loans_generate_receipt': 'loans',
            'loans_modify_terms': 'loans',
            'loans_close_loan': 'loans',
            'loans_export_data': 'loans',
            
            'repayments': 'repayments',
            'portfolio': 'portfolio',
            'reports_statements': 'reports',
            'documents': 'documents',
            'customer_documents': 'documents',
            'payment_receipts': 'receipts',
            'notifications': 'notifications',
            'settings': 'settings',
            'branch_settings': 'settings',
            'system_settings': 'settings',
        }
        
        return page_mapping.get(module, module.split('_')[0] if '_' in module else module)