from rest_framework import serializers
from apps.core.permissions.role_permission import validate_permissions_structure, get_role_based_permissions, merge_permissions
from apps.users.models import User
from apps.core.utils import validate_and_normalize_email, validate_name
from apps.core.services import send_email_otp
from apps.core.permissions.permissions import get_permissions 



class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)
    confirm_password = serializers.CharField(write_only=True, required=False)
    
    class Meta:
        model = User
        fields = [
            'id', 'name', 'email', 'role', 'permissions',
            'refer_code', 'is_staff', 'is_superuser', 
            'is_email_verified', 'password', 'confirm_password',
            'is_active'
        ]
        read_only_fields = [
            'id', 'refer_code', 'is_staff', 'is_superuser','role', 'permissions',
            'is_email_verified', 'is_active'
        ]
        extra_kwargs = {
            'password': {'write_only': True},
            'confirm_password': {'write_only': True},
        }
    
    def validate_email(self, value):
        """Email validation"""
        if not value:
            raise serializers.ValidationError("Email is required")
        
        # Normalize email
        normalized_email = validate_and_normalize_email(value)
        
        # Check for existing user with this email
        if self.instance:
            # Update case
            if User.objects.filter(email__iexact=normalized_email).exclude(id=self.instance.id).exists():
                raise serializers.ValidationError("This email already exists.")
        else:
            # Create case
            if User.objects.filter(email__iexact=normalized_email).exists():
                raise serializers.ValidationError("This email already exists.")
        
        return normalized_email
    
    def validate_name(self, value):
        """Name validation"""
        return validate_name(value)
    
    def validate_permissions(self, value):
        """Validate permissions structure"""
        if value and not validate_permissions_structure(value):
            raise serializers.ValidationError("Invalid permissions structure")
        return value
    
    def validate(self, data):
        """Main validation"""
        # New registration validation
        if not self.instance:
            password = data.get('password')
            confirm_password = data.get('confirm_password')
            
            if not password:
                raise serializers.ValidationError({"password": "Password is required"})
            
            if not confirm_password:
                raise serializers.ValidationError({"confirm_password": "Confirm password is required"})
            
            if password != confirm_password:
                raise serializers.ValidationError({"confirm_password": "Passwords don't match"})
            
            # Password strength validation
            if len(password) < 8:
                raise serializers.ValidationError({"password": "Password must be at least 8 characters long"})
        
        # Update validation
        else:
            password = data.get('password')
            confirm_password = data.get('confirm_password')
            
            # If password is being changed
            if password or confirm_password:
                if not password:
                    raise serializers.ValidationError({"password": "Password is required when changing password"})
                
                if not confirm_password:
                    raise serializers.ValidationError({"confirm_password": "Confirm password is required"})
                
                if password != confirm_password:
                    raise serializers.ValidationError({"confirm_password": "Passwords don't match"})
                
                # Password strength validation
                if len(password) < 8:
                    raise serializers.ValidationError({"password": "Password must be at least 8 characters long"})
        
        # Role validation
        role = data.get('role')
        request = self.context.get('request')
        
        if request and request.user:
            current_user = request.user
            if role == 'admin' and not current_user.is_superuser:
                raise serializers.ValidationError({"role": "Only superuser can assign admin role"})
        
        return data
    
    def create(self, validated_data):
        """Create new user"""
        validated_data.pop('confirm_password', None)
        
        if 'role' not in validated_data:
            validated_data['role'] = 'user'
        
        user = User.objects.create_user(**validated_data)
        email = validated_data.get('email')
        
        send_email_otp(user, email)
        
        return user
    
    def update(self, instance, validated_data):
        """Update user"""
        # Remove password fields from validated data
        password = validated_data.pop('password', None)
        validated_data.pop('confirm_password', None)
        
        # Update user
        user = super().update(instance, validated_data)
        
        # Update password if provided
        if password:
            user.set_password(password)
            user.save()
        
        return user
    

    def to_representation(self, instance):
        """Format response"""
        data = super().to_representation(instance)
        data.pop('password', None)
        data.pop('confirm_password', None)
        
        if instance.is_superuser:
            from apps.core.permissions.permissions import get_permissions
            data['permissions'] = get_permissions()
        else:
            base_permissions = get_role_based_permissions(instance.role)
            
            if instance.permissions and isinstance(instance.permissions, dict):
                data['permissions'] = merge_permissions(base_permissions, instance.permissions)
            else:
                data['permissions'] = base_permissions
        
        return data


class LoginSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    password = serializers.CharField(required=True, write_only=True)
    
    def validate(self, data):
        email = data.get('email')
        password = data.get('password')
        
        # Check if email is provided
        if not email:
            raise serializers.ValidationError({
                "email": "Email is required"
            })
        
        # Check if password is provided
        if not password:
            raise serializers.ValidationError({
                "password": "Password is required"
            })
        
        try:
            user = User.objects.get(email__iexact=email)
        except User.DoesNotExist:
            raise serializers.ValidationError("Invalid email or password")
        
        # Check password
        if not user.check_password(password):
            raise serializers.ValidationError("Invalid email or password")
        
        # Check if user is active
        if not user.is_active:
            raise serializers.ValidationError("Account is not active. Please verify your email.")
        
        # Check if email is verified
        if not user.is_email_verified:
            raise serializers.ValidationError("Email is not verified. Please verify your email first.")
        
        data['user'] = user
        return data


class UserPermissionsUpdateSerializer(serializers.Serializer):
    permissions = serializers.JSONField(required=True)
    
    def validate_permissions(self, value):
        if not isinstance(value, dict):
            raise serializers.ValidationError("Permissions must be a JSON object")
        
        if not validate_permissions_structure(value):
            raise serializers.ValidationError("Invalid permissions structure")
        
        return value


class UserRoleChangeSerializer(serializers.Serializer):
    role = serializers.ChoiceField(choices=User.ROLE_CHOICES, required=True)
    
    def validate_role(self, value):
        request = self.context.get('request')
        user = self.context.get('user')
        
        if request and user:
            # Check if user is trying to change their own role
            if user == request.user:
                raise serializers.ValidationError("You cannot change your own role")
        
        return value