from rest_framework import serializers, validators
from shop_management.serializers.data.base import DataRootSerializer
from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.core.mail import send_mail
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from shop_management.models.data.shop import Shop
from account.permissions import permissions_for_role


User = get_user_model()
# FRONTEND_URL = 'https://sanbawar.com'  # Update this to your actual frontend URL



class UserSerializer(serializers.ModelSerializer):
    assigned_shops = serializers.PrimaryKeyRelatedField(
        many=True,
        read_only=True,
    )

    class Meta:
        model = get_user_model()
        fields = [
            "id",
            "username",
            "email",
            "first_name",
            "last_name",
            "password",
            "is_seller",
            "tazkira_number",
            "phone_number",
            "address",
            "work_license_copy",
            "tazkira_copy",
            "shop_name",
            "verified",
            "is_staff",
            "is_superuser",
            "allowed_tabs",
            "system_role",
            "action_permissions",
            "image",
            "date_joined","is_visible_phone",
            "is_email_verified",
            "shop_address",
            "is_mobile_verified",
            "gender",
            "temporary_verification_expiration",
            "description",
            "created_at",
            "updated_at",
            "longitude",
            "latitude",
            "assigned_shops",
        ]
        extra_kwargs = {
            "password": {"write_only": True},
            "work_license_copy": {"required": False},
            "tazkira_copy": {"required": False},
            "temporary_verification_expiration": {"required": False},
            "username": {
                "required": False,
                "allow_blank": True,
                "allow_null": True,
            },
            "email": {
                "required": False,
                "allow_blank": True,
                "allow_null": True,
                "validators": [
                    validators.UniqueValidator(
                        queryset=get_user_model().objects.all(),
                        message="A user with this Email already exists",
                    )
                ],
            },
            "phone_number": {
                "required": False,
                "allow_blank": True,
                "validators": [
                    validators.UniqueValidator(
                        queryset=get_user_model().objects.all(),
                        message="A user with this Phone Number already exists",
                    )
                ],
            },
            "email_otp": {"read_only": True},
            "action_permissions": {"read_only": True},
        }




    def _parse_allowed_tabs(self, value):
        if value is None:
            return []
        if isinstance(value, list):
            return value
        if isinstance(value, str):
            import json
            try:
                return json.loads(value) if value.strip() else []
            except (ValueError, TypeError, AttributeError):
                return []
        return []

    def create(self, validated_data):
        """
        Create and return a new user, ensuring password is hashed and OTP is generated.
        """
        assigned_shops = validated_data.pop("assigned_shops", [])
        password = validated_data.pop("password")
        if "allowed_tabs" in validated_data:
            validated_data["allowed_tabs"] = self._parse_allowed_tabs(validated_data["allowed_tabs"])
        validated_data["action_permissions"] = permissions_for_role(validated_data.get("system_role"))
        user = get_user_model().objects.create_user(
            **validated_data,
            password=password
        )
        user.assigned_shops.set(assigned_shops)
        return user
        
    

    def update(self, instance, validated_data):
        """
        Update and return an existing user, ensuring password is hashed if provided.
        """
        assigned_shops = validated_data.pop("assigned_shops", None)
        instance.username = validated_data.get("username", instance.username)
        instance.email = validated_data.get("email", instance.email)
        instance.first_name = validated_data.get("first_name", instance.first_name)
        instance.last_name = validated_data.get("last_name", instance.last_name)
        instance.is_seller = validated_data.get("is_seller", instance.is_seller)
        instance.tazkira_number = validated_data.get("tazkira_number", instance.tazkira_number)
        instance.phone_number = validated_data.get("phone_number", instance.phone_number)
        instance.address = validated_data.get("address", instance.address)
        instance.work_license_copy = validated_data.get("work_license_copy", instance.work_license_copy)
        instance.tazkira_copy = validated_data.get("tazkira_copy", instance.tazkira_copy)
        instance.shop_name = validated_data.get("shop_name", instance.shop_name)
        instance.verified = validated_data.get("verified", instance.verified)
        instance.is_staff = validated_data.get("is_staff", instance.is_staff)
        instance.is_superuser = validated_data.get("is_superuser", instance.is_superuser)
        instance.allowed_tabs = self._parse_allowed_tabs(
            validated_data.get("allowed_tabs", instance.allowed_tabs)
        )
        instance.system_role = validated_data.get("system_role", instance.system_role)
        instance.action_permissions = permissions_for_role(instance.system_role)
        instance.image = validated_data.get("image", instance.image)
        instance.is_visible_phone = validated_data.get("is_visible_phone", instance.is_visible_phone)
        instance.shop_address = validated_data.get("shop_address", instance.shop_address)
        instance.is_mobile_verified = validated_data.get("is_mobile_verified", instance.is_mobile_verified)
        instance.is_email_verified = validated_data.get("is_email_verified",instance.is_email_verified)
        instance.gender = validated_data.get("gender",instance.gender)
        instance.temporary_verification_expiration = validated_data.get("temporary_verification_expiration",instance.temporary_verification_expiration)
        instance.description = validated_data.get("description", instance.description)
        
        instance.created_at = validated_data.get("created_at", instance.created_at)
        instance.updated_at = validated_data.get("updated_at", instance.updated_at)
        instance.longitude = validated_data.get("longitude", instance.longitude)
        instance.latitude = validated_data.get("latitude", instance.latitude)
    
        # Handle password separately
        password = validated_data.get("password", None)
        if password:
            instance.set_password(password)
    
        instance.save()
        if assigned_shops is not None:
            instance.assigned_shops.set(assigned_shops)
        return instance

class AdminUserSerializer(UserSerializer):
    assigned_shops = serializers.PrimaryKeyRelatedField(
        queryset=Shop.objects.all(),
        many=True,
        required=False,
    )

    def validate(self, attrs):
        is_superuser = attrs.get(
            "is_superuser",
            getattr(self.instance, "is_superuser", False),
        )
        assigned_shops = attrs.get("assigned_shops")
        if assigned_shops is None and self.instance is not None:
            assigned_shops = list(self.instance.assigned_shops.all())

        if not is_superuser and not assigned_shops:
            raise serializers.ValidationError(
                {"assigned_shops": "Select at least one branch for a non-super-admin user."}
            )
        return attrs




class LoginSerializer(serializers.Serializer):
    login = serializers.CharField()  # This field will accept either email, username, or phone_number
    password = serializers.CharField(write_only=True)
    selected_branch = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    def validate(self, data):
        """
        Validate the provided login field (email/username/phone_number) and password.
        """
        login = data.get("login")
        password = data.get("password")

        # Try to get the user by email, username, or phone number
        try:
            user = User.objects.get(
                Q(email=login) | Q(username=login) | Q(phone_number=login)
            )
        except User.DoesNotExist:
            raise serializers.ValidationError(_("Invalid login or password."))

        # Check if the provided password is correct
        if not user.check_password(password):
            raise serializers.ValidationError(_("Invalid login or password."))

        # Check if the user is active
        if not user.is_active:
            raise serializers.ValidationError(_("This user account is disabled."))

        selected_branch = data.get("selected_branch")
        if not user.is_superuser:
            accessible_branches = Shop.objects.filter(
                Q(owner=user) | Q(assigned_users=user)
            ).distinct().order_by("id")
            if selected_branch:
                branch = accessible_branches.filter(pk=selected_branch).first()
                if not branch:
                    raise serializers.ValidationError(
                        {"selected_branch": _("You do not have access to this branch.")}
                    )
            else:
                branch = accessible_branches.first()
            if not branch:
                raise serializers.ValidationError(
                    {"selected_branch": _("No branch is assigned to this user. Contact an administrator.")}
                )
            data["selected_branch"] = str(branch.pk)
        
        # Add the user to validated data
        data["user"] = user
        return data





class UserListSerializer(serializers.ModelSerializer):
    """
    Serializer for listing users, includes all fields.
    """
    class Meta: 
        model = User
        fields = '__all__'
        
class UserProfileSerializer(serializers.ModelSerializer):
    
    class Meta: 
        model = User
        fields = [
            "id",
            "username",
            "email",
            "first_name",
            "last_name",
            "password",
            "is_seller",
            "tazkira_number",
            "phone_number",
            "address",
            "work_license_copy",
            "tazkira_copy",
            "shop_name",
            "image",
            "is_visible_phone",
            "is_email_verified",
            "verified",
            "shop_address",
            "gender",
            "created_at",
            
            
        ]
        extra_kwargs = {"password": {"write_only": True}}




class ResendOTPSerializer(serializers.Serializer):
    email = serializers.EmailField()











