from rest_framework import serializers
from django.contrib.auth.models import User, Group
from django.core.validators import validate_email
from django.core.exceptions import ValidationError as DjangoValidationError
from .models import (
    ImplementerDetails,
    TblUserOrganizationAuth,
    UserProfile
)
from masters.serializers import UserRecruiterMappingSerializer

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "username", "email"]   # pick only safe fields


class AuthGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = ("id", "name")

class TblUserOrganizationAuthSerializer(serializers.ModelSerializer):

    class Meta:
        model = TblUserOrganizationAuth
        fields = ('__all__')

class AuthUserPermissionsSerializer(serializers.ModelSerializer):
    groups = AuthGroupSerializer(many=True, read_only=True)
    auth_user_organization = TblUserOrganizationAuthSerializer(many=True, read_only=True)
    client_mappings = serializers.SerializerMethodField()
    recruiters = UserRecruiterMappingSerializer(
    many=True,
    read_only=True,
    source="recruiter_mappings"
    )
    profile_image = serializers.ImageField(
        source="profile.profile_image",
        required=False,
        allow_null=True
    )
    display_column_preference = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = (
            'id', 
            'username', 
            'password', 
            'first_name', 
            'last_name', 
            'email',
            'groups',
            'is_superuser', 
            'auth_user_organization', 
            "client_mappings",
            "recruiters",
            'profile_image',
            "display_column_preference",
            'is_active', 
            'last_login'
        )
    def get_client_mappings(self, obj):
        return [
            {"client": m.client_id}
            for m in obj.client_mappings.all()
        ]
    
    def get_display_column_preference(self, obj):

        DEFAULT_TABLE_PREFERENCES = {
            "jd_table": {
                "jd_id": True,
                "title": True,
                "client": True,
                "type": True,
                "location": True,
                "recruiters": True,
                "stage": True,
                "status": True,
                "created_dt": True,
                "updated_dt": True
            }
        }

        profile = getattr(obj, "profile", None)

        if profile and profile.display_column_preference:
            return profile.display_column_preference

        return DEFAULT_TABLE_PREFERENCES
    
    def validate_email(self, value):

        user_id = self.instance.id if self.instance else None

        qs = User.objects.filter(email__iexact=value)
        if user_id:
            qs = qs.exclude(id=user_id)

        if qs.exists():
            raise serializers.ValidationError("This email already exists.")

        return value

class OrganizationDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = ImplementerDetails
        fields = "__all__"
    
    def validate_name(self, value):
        qs = ImplementerDetails.objects.filter(name__iexact=value)

        if self.instance:
            qs = qs.exclude(id=self.instance.id)

        if qs.exists():
            raise serializers.ValidationError(
                "Implementer Name already exists."
            )
        return value

    def validate_email_details(self, value):
        if not isinstance(value, list):
            raise serializers.ValidationError("email_details must be a list")

        emails_in_payload = set()

        for item in value:
            if not isinstance(item, dict):
                raise serializers.ValidationError(
                    "Each email_details item must be an object"
                )

            email = item.get("email")
            if not email:
                raise serializers.ValidationError(
                    "Each email_details item must contain 'email'"
                )

            # Validate email format
            try:
                validate_email(email)
            except DjangoValidationError:
                raise serializers.ValidationError(
                    f"Invalid email format: {email}"
                )

            # Check duplicate in same request
            if email.lower() in emails_in_payload:
                raise serializers.ValidationError(
                    f"Duplicate email in request: {email}"
                )
            emails_in_payload.add(email.lower())

            # Check duplicate across DB
            qs = ImplementerDetails.objects.filter(
                email_details__contains=[{"email": email}]
            )

            if self.instance:
                qs = qs.exclude(id=self.instance.id)

            if qs.exists():
                raise serializers.ValidationError(
                    f"Email already exists in another Implementer: {email}"
                )

        return value

    def validate(self, attrs):
        """
        Validate country code + contact number combination
        """
        country_code = attrs.get(
            "country_code",
            self.instance.country_code if self.instance else None
        )
        contact_number = attrs.get(
            "contact_number",
            self.instance.contact_number if self.instance else None
        )

        if country_code and contact_number:
            qs = ImplementerDetails.objects.filter(
                country_code=country_code,
                contact_number=contact_number
            )

            if self.instance:
                qs = qs.exclude(id=self.instance.id)

            if qs.exists():
                raise serializers.ValidationError({
                    "contact_number":
                        "Implementer contact number already exists with this country code."
                })

        return attrs
    
class UserProfileImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = ("profile_image")