from rest_framework import serializers
from django.utils import timezone
from django.db import transaction
from django.contrib.auth import get_user_model

from apps.core.services import PhoneUniquenessService
from apps.core.utils import generate_secure_password
from apps.userprofile.models import UserProfile
from apps.permissions.models import UserCompanyRole, Role
from apps.permissions.services import set_active_company, sync_companies


User = get_user_model()


class CreateUserSerializer(serializers.ModelSerializer):
    profile = serializers.DictField()
    company_roles = serializers.ListField(
        child=serializers.DictField(), required=False
    )

    email = serializers.EmailField(
        required=True,
        validators=[],  # ⚠ Remove default UniqueValidator
    )

    class Meta:
        model = User
        fields = [
            "email",
            "profile",
            "company_roles",
        ]

    def validate_email(self, value):
        value = value.lower().strip()
        existing_user = User.objects.filter(email=value).first()
        if existing_user:
            # Only allow if we are assigning a company
            company_roles = self.initial_data.get("company_roles", [])
            if not company_roles:
                raise serializers.ValidationError({
                    "email": "User with this email already exists. "
                             "Specify a company to add."
                })
        return value

    def validate(self, attrs):
        profile_data = attrs.get("profile", {})
        phone_number = profile_data.get("phone_number")
        email = attrs.get("email")

        if phone_number:
            existing_user = User.objects.filter(email=email).first()

            try:
                PhoneUniquenessService.assert_unique(
                    phone_number,
                    exclude_user_id=existing_user.id if existing_user else None,
                )
            except ValueError as e:
                raise serializers.ValidationError({
                    "profile": {
                        "phone_number": str(e)
                    }
                })

        return attrs

    @transaction.atomic
    def create(self, validated_data):
        email = validated_data.get("email")
        user = User.objects.filter(email=email).first()
        company_roles = validated_data.pop("company_roles", [])

        if user and not company_roles:
            raise serializers.ValidationError({
                "company_roles": "Company roles are required "
                                 "when adding an existing user to a company."
            })

        profile_data = validated_data.pop("profile", {})

        first_name = profile_data.get("first_name", None)
        last_name = profile_data.get("last_name", None)
        phone_number = profile_data.get("phone_number", None)
        image = profile_data.get("image")

        if not user:
            generated_password = generate_secure_password(12)
            validated_data["password"] = generated_password

            user = User.objects.create_user(**validated_data)
            user._generated_password = generated_password

            UserProfile.objects.create(
                user=user,
                first_name=first_name,
                last_name=last_name,
                phone_number=phone_number,
                image=image,
            )

        memberships = []
        for role in company_roles:
            if "company_id" not in role or "role_id" not in role:
                raise serializers.ValidationError({
                    "company_roles": "Company and Role are required"
                })

            role_object = Role.objects.filter(
                id=role["role_id"],
                company_id=role["company_id"]
            ).first()
            if not role_object:
                raise serializers.ValidationError({
                    "company_roles": f"Role with id {role['role_id']} "
                    f"does not exist in company "
                    f"{role['company_id']}."
                })

            membership, created = UserCompanyRole.objects.get_or_create(
                user=user,
                company_id=role["company_id"],
                defaults={
                    'role_id':role["role_id"],

                    'first_name':first_name,
                    'last_name':last_name,

                    'invited_at':timezone.now(),
                    'is_active':True,
                    'is_default':False,
                    'is_owner':False,
                    'is_available':True,

                    'phone':phone_number,
                    'designation':role_object.name,
                    'image':image,

                    'created_by':(
                        self.context["request"].user
                        if self.context.get('request')
                        else None
                    )
                }
            )

            if not created:
                raise serializers.ValidationError({
                    "company_roles": f"User is already a member of {membership.company.name}."
                })

            memberships.append(membership)

        sync_companies(user)
        set_active_company(user, memberships)

        return user
