from rest_framework import serializers
from django.contrib.auth import get_user_model
from apps.companies.models import Company
from apps.permissions.models import UserCompanyRole, Permission, Role

from apps.userprofile.serializers import UserProfileSerializer


User = get_user_model()


class PermissionSerializer(serializers.ModelSerializer):
    """Simplified permission serializer"""
    class Meta:
        model = Permission
        fields = ['id', 'name', 'codename']


class RoleWithPermissionsSerializer(serializers.ModelSerializer):
    """Serializer for Role with its permissions"""
    permissions = serializers.SerializerMethodField()

    class Meta:
        model = Role
        fields = ['id', 'name', 'description', 'is_active', 'permissions']

    def get_permissions(self, obj):
        perms =getattr(obj, '_cached_permissions', None)

        if perms is None:
            perms = obj.permissions.filter(is_active=True)
        
        return PermissionSerializer(perms, many=True).data


class RolePermissionHelper:
    """
    Central place to fetch user's roles and permissions with caching.
    """
    
    @staticmethod
    def get_user_role_in_company(user, company):
        """
        Uses pre-fetched role if available; otherwise queries only once.
        """

        for ucr in getattr(user, '_cached_roles', []):
            if ucr.company_id == company.id:
                return ucr.role

        ucr = UserCompanyRole.objects.filter(
            user=user,
            company=company,
            is_active=True
        ).select_related('role').first()
        
        return ucr.role if ucr else None
    
    @staticmethod
    def get_role_permissions(role):
        """Get permissions for a role"""
        if not role:
            return []
        
        return PermissionSerializer(
            role.permissions.filter(is_active=True), many=True
        ).data
    
    @staticmethod
    def get_role_name(user, company):
        """Get user's role name in a company"""
        role = RolePermissionHelper.get_user_role_in_company(user, company)
        return role.name if role else None
    
    @staticmethod
    def get_user_permissions_in_company(user, company):
        """Get user's permissions in a specific company"""
        role = RolePermissionHelper.get_user_role_in_company(user, company)
        return RolePermissionHelper.get_role_permissions(role)


class CompanyUserSerializer(serializers.ModelSerializer):
    """
    Full user serializer with company & role information
    """


    profile = UserProfileSerializer(required=False)
    first_name = serializers.CharField(source='profile.first_name', read_only=True)
    last_name = serializers.CharField(source='profile.last_name', read_only=True)
    phone_number = serializers.CharField(source='profile.phone_number', read_only=True)
    
    company_id = serializers.SerializerMethodField()
    company_name = serializers.SerializerMethodField()
    companies_count = serializers.SerializerMethodField()
    companies_with_roles = serializers.SerializerMethodField()
    role = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id', 'username', 'email', 'user_type', 'is_active','is_available', 'profile',
            'first_name', 'last_name', 'phone_number',
            'company_id', 'company_name',
            'role',
            'companies_count', 'companies_with_roles',
        ]

    def get_company_id(self, obj):
        """Get company ID from context"""
        company = self.context.get('company')
        return company.id if company else None

    def get_company_name(self, obj):
        """Get company name from context"""
        company = self.context.get('company')
        return company.name if company else None

    def get_companies_count(self, obj):
        """Get count of companies user belongs to"""
        return obj.companies.count()

    def get_role(self, obj):
        """
        Return the user's role in the company passed via query params (context).
        """
        
        company = self.context.get('company')
        if not company:
            return None
        
        role = RolePermissionHelper.get_user_role_in_company(obj, company)
        if not role:
            return None
        
        return RoleWithPermissionsSerializer(role).data

    def get_companies_with_roles(self, obj):
        """Get all companies and user's role in each company"""
        results = []

        cached_roles = {ucr.company_id: ucr.role for ucr in getattr(obj, '_cached_roles', [])}

        for company in obj.companies.all():

            role = cached_roles.get(company.id)

            results.append({
                'id': company.id,
                'name': company.name,
                'is_active': company.is_active,
                'role': RoleWithPermissionsSerializer(role).data if role else None
            })

        return results


class UserCompanyWithRoleSerializer(serializers.Serializer):
    """Serializer for a single company with user's role and permissions"""
    company_name = serializers.CharField(source='name')
    role = serializers.SerializerMethodField()
    permissions = serializers.SerializerMethodField()
    
    def get_role(self, obj):
        """Get user's role name in this company using helper"""
        user = self.context.get('user')
        return RolePermissionHelper.get_role_name(user, obj) if user else None
    
    def get_permissions(self, obj):
        """Get permissions for user's role in this company using helper"""
        user = self.context.get('user')
        return RolePermissionHelper.get_user_permissions_in_company(user, obj) if user else []
