from rest_framework import serializers
from .models import *
from django.contrib.auth.models import Group, Permission
import random
import string
from .utils import *
from suscription.models import subscribe, Plan
from drf_spectacular.utils import extend_schema_field
from product.models import MainCategory, PlanPurchase
from order.models import Cart
from datetime import timedelta, datetime
from rest_framework.validators import UniqueValidator

# ****** Admin User


class AdminRegisterser(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "email", "password", "full_name", "created_at"]
        extra_kwargs = {"password": {"read_only": True}}

    def create(self, validated_data):
        return User.objects.create_superuser(**validated_data)


class AdminLoginSer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "password"]


class AdminPasswordResetRequestSer(serializers.ModelSerializer):
    email = serializers.EmailField()

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

    def validate_email(self, value):
        if not User.objects.filter(email=value).exists():
            raise serializers.ValidationError("No user is associated with this email")
        return value


class AdminPasswordResetSer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField()
    confirm_password = serializers.CharField()
    # otp = serializers.CharField(max_length = 4)


class UserPermissionSer(serializers.Serializer):
    user = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.filter(is_vendor=True)
    )
    permission = serializers.PrimaryKeyRelatedField(
        queryset=Permission.objects.all(), many=True
    )

    def create(self, validated_data):
        user = validated_data["user"]
        permissions = validated_data["permission"]

        # user_obj = User.objects.filter(id = user)

        # Add the permissions to the user
        user.user_permissions.set(permissions)
        # user_obj.user_permissions.set(permissions)

        return user


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


class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = ["id", "name", "permissions"]


# ***** Vendor
class VendorRegisterSer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)
    password2 = serializers.CharField(write_only=True, required=True)
    main_category = serializers.CharField(write_only=True, required=True)
    count = serializers.IntegerField(read_only=True)
    plan_name = serializers.SerializerMethodField()
    is_expired = serializers.SerializerMethodField()

    @extend_schema_field(serializers.CharField)
    def get_plan_name(self, obj):
        subscription = PlanPurchase.objects.filter(vendor=obj).order_by('-id').first()
        if subscription and subscription.categories_plan:
            return subscription.categories_plan.name
        return None

        # subscription = subscribe.objects.filter(user=obj).first()
        # if subscription:
        #     return subscription.plan.name
        # return None

    @extend_schema_field(serializers.BooleanField)
    def get_is_expired(self, obj):
        subscription = subscribe.objects.filter(user=obj).first()
        if subscription:
            return subscription.is_expired
        return None

    class Meta:
        model = User
        fields = [
            "id",
            "email",
            "count",
            "plan_name",
            "is_expired",
            "full_name",
            "is_active",
            "is_staff",
            "phone",
            "address",
            "apartment_number",
            "street_name",
            "city",
            "state",
            "zip_code",
            "t_and_c",
            "location",
            "lat",
            "long",
            "is_vendor",
            "main_category",
            "is_buyer",
            "password",
            "password2",
            "shop_name",
            "doc1",
            "doc2",
            "doc3",
            "doc4",
            "image",
            "is_document",
            "design",
            "status",
            "created_at",
        ]

    def validate(self, attrs):
        password = attrs.get("password")
        password2 = attrs.get("password2")

        if password or password2:
            if password != password2:
                raise serializers.ValidationError(
                    {"password": "Password fields didn't match."}
                )
        attrs.pop("password2", None)
        return attrs

    def create(self, validated_data):
        password = validated_data.pop("password", None)
        main_category_id = validated_data.pop('main_category', None)
        if main_category_id:  
            validated_data['main_category'] = MainCategory.objects.get(id=main_category_id) 
        user = User(**validated_data)
        if password:
            user.set_password(password)
        user.save()
        return user

    def to_representation(self, instance):
        representation = super().to_representation(instance)

        representation["otp"] = instance.otp
        representation["plan_name"] = self.get_plan_name(instance)
        representation["is_expired"] = self.get_is_expired(instance)

        return representation


class VendorRegisterOTPVerifySer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "otp"]


class VendorPasswordResetRequestSer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "phone"]

    def validate_email(self, value):
        if not User.objects.filter(email=value).exists():
            raise serializers.ValidationError("No user is associated with this email")
        return value


class VendorPasswordResetOTPVerifySer(serializers.Serializer):
    email = serializers.EmailField()
    otp = serializers.CharField(max_length=4)


class VendorPasswordResetSer(serializers.ModelSerializer):
    email = serializers.EmailField()
    password = serializers.CharField(write_only=True, required=True)
    confirm_password = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = User
        fields = ["id", "email", "password", "confirm_password"]

    def validate(self, attrs):
        if attrs["password"] != attrs["confirm_password"]:
            raise serializers.ValidationError(
                {"password": "Password fields didn't match."}
            )
        attrs.pop("confirm_password")
        return attrs


class VendorLoginSer(serializers.ModelSerializer):
    doc1_url = serializers.SerializerMethodField(read_only=True)

    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "password", "doc1_url", "doc1"]
        extra_kwargs = {"doc1": {"write_only": True}}

    @extend_schema_field(serializers.URLField)
    def get_doc1_url(self, obj):
        request = self.context.get("request")
        if obj.doc1:
            return request.build_absolute_uri(obj.doc1.url)
        return ""

    # def create(self, validated_data):
    #     # Hash the password before saving
    #     password = validated_data.pop('password')
    #     validated_data['password'] = make_password(password)
    #     return super().create(validated_data)

    # def update(self, instance, validated_data):
    #     # Hash the password before saving
    #     if 'password' in validated_data:
    #         password = validated_data.pop('password')
    #         validated_data['password'] = make_password(password)
    #     return super().update(instance, validated_data)


class VendorProfileSer(serializers.ModelSerializer):
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = User
        fields = "__all__"


class BuyerRegisterSer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True, required=False, allow_blank=True, allow_null=True
    )
    password2 = serializers.CharField(
        write_only=True, required=False, allow_blank=True, allow_null=True
    )
    location = serializers.CharField(max_length=100, allow_blank=True, allow_null=True)
    invited_by_code = serializers.CharField(write_only=True, required=False)    


    class Meta:
        model = User
        fields = [
            "id",
            "email",
            "full_name",
            "phone",
            "address",
            "apartment_number",
            "street_name",
            "city",
            "state",
            "zip_code",
            "t_and_c",
            "location",
            "is_vendor",
            "is_buyer",
            "password",
            "password2",
            "invited_by_code",
            "referral_code",
            "image",
            "design",
            "total_points",
            "created_at",
        ]

    # def validate(self, attrs):
    #     if attrs['password'] != attrs['password2']:
    #         raise serializers.ValidationError({"password": "Password fields didn't match."})
    #     attrs.pop('password2')
    #     return attrs

    def validate(self, attrs):
        password = attrs.get("password")
        password2 = attrs.get("password2")
        invited_by_code = attrs.get("invited_by_code")

        if password or password2:
            if password != password2:
                raise serializers.ValidationError(
                    {"password": "Password fields didn't match."}
                )
            
        if invited_by_code:
            referral_user = User.objects.filter(
                is_buyer=True,
                referral_code=invited_by_code,
                # otp_verified=True
            ).first()

            if not referral_user or (not referral_user.sso_id and not referral_user.otp_verified):
                raise serializers.ValidationError(
                    {"referral_code": "Invalid referral code or user not verified."}
                )
            
            # if not referral_user:
            #     raise serializers.ValidationError(
            #         {"referral_code": "Invalid referral code or user not verified."}
            #     )
            
            # if not referral_user.sso_id and referral_user.otp_verified!=True :
            #     raise serializers.ValidationError(
            #         {"referral_code": "Invalid referral code or user not verified."}
            #     )

            attrs['referral_user_obj'] = referral_user

        attrs.pop("password2", None)
        return attrs

    def create(self, validated_data):
        password = validated_data.pop("password", None)
        validated_data.pop("invited_by_code", None)

        referral_user = validated_data.pop("referral_user_obj", None)

        if referral_user:
            validated_data['referred_by'] = referral_user

        user = User(**validated_data)
        user.is_active = True  
        user.is_staff = True

        if not user.referral_code :
            user.referral_code = generate_unique_referral_code()

        if password:
            user.set_password(password)
        user.save()
        return user

    # def create(self, validated_data):
    #     password = validated_data.pop('password', None)
    #     user = User(**validated_data)
    #     if password:
    #         user.password = password  # Assign password directly without hashing
    #     user.save()
    #     return user

    def update(self, instance, validated_data):
        password = validated_data.pop("password", None)
        if password:
            instance.set_password(password)
        return super().update(instance, validated_data)

    def remove_fields(self, fields_to_remove):
        """Remove specified fields from the serializer."""
        for field in fields_to_remove:
            self.fields.pop(field, None)

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        lat = representation.get("lat")
        long = representation.get("long")

        if lat and long:
            representation["location"] = [float(lat), float(long)]

        return representation


class BuyerRegisterOTPVerifySer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "otp"]


class BuyerPasswordResetRequestSer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        model = User
        fields = ["id", "email", "phone"]

    def validate_email(self, value):
        if not User.objects.filter(email=value).exists():
            raise serializers.ValidationError("No user is associated with this email")
        return value


class BuyerPasswordResetOTPVerifySer(serializers.Serializer):
    email = serializers.EmailField()
    otp = serializers.CharField(max_length=4)


class BuyerPasswordResetSer(serializers.ModelSerializer):

    email = serializers.EmailField()
    password = serializers.CharField(write_only=True, required=True)
    confirm_password = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = User
        fields = ["id", "email", "password", "confirm_password"]

    def validate(self, attrs):
        if attrs["password"] != attrs["confirm_password"]:
            raise serializers.ValidationError({"password": "Passwords do not match."})
        attrs.pop("confirm_password")
        return attrs


class BuyerLoginSer(serializers.ModelSerializer):
    email = serializers.EmailField()

    class Meta:
        # model=BuyerLogin
        model = User
        fields = ["id", "email", "password"]


class BuyerProfileSer(serializers.ModelSerializer):
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = User
        fields = "__all__"
        # fields = ['id', '']


class UserProfileSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(read_only=True)
    plan_name = serializers.SerializerMethodField()
    is_expired = serializers.SerializerMethodField()

    email = serializers.EmailField(
        required=True,
        validators=[
            UniqueValidator(
                queryset=User.objects.all(),
                message="Another account is already registered with this e‑mail."
            )
        ],
    )

    class Meta:
        model = User
        fields = "__all__"

    @extend_schema_field(serializers.CharField)
    def get_plan_name(self, obj):
        subscription = PlanPurchase.objects.filter(vendor=obj).order_by('-id').first()
        if subscription and subscription.categories_plan:
            return subscription.categories_plan.name
        return None
    # def get_plan_name(self, obj):
    #     subscription = subscribe.objects.filter(user=obj).first()
    #     if subscription:
    #         return subscription.plan.name
    #     return None

    @extend_schema_field(serializers.BooleanField)
    def get_is_expired(self, obj):
        subscription = subscribe.objects.filter(user=obj).first()
        if subscription:
            return subscription.is_expired
        return None

    def get_doc1_url(self, obj):
        request = self.context.get("request")
        return request.build_absolute_uri(obj.doc1.url)

    def to_representation(self, instance):
        representation = super().to_representation(instance)

        representation.pop(
            "password", None
        )  # Remove the password field from the response

        permission_ids = representation.get("user_permissions", [])
        permissions = Permission.objects.filter(id__in=permission_ids)
        serialized_permissions = PermissionSerializer(permissions, many=True).data
        representation["user_permissions"] = serialized_permissions
        lat = representation.get("lat")
        long = representation.get("long")
        if lat and long:
            representation["location"] = [float(lat), float(long)]
        representation["plan_name"] = self.get_plan_name(instance)
        representation["is_expired"] = self.get_is_expired(instance)
        return representation

    def update(self, instance, validated_data):
        request = self.context.get('request')
        user = request.user if request else None

        # Extract new reason from validated data
        active_status = validated_data.get("is_active", False)
        new_reason = validated_data.get("reason", None)
        # Perform the default update logic
        instance = super().update(instance, validated_data)
        # Check if 'reason' field is updated
        if active_status:
            data = {
                "subject": "e360 Mart: Account approved!",
                "name": instance.full_name,
                "to_email": instance.email,
            }
            send_approval_email(data)
        if new_reason:
            body = "Reason is : " + new_reason
            data = {
                "subject": "Vendor account block",
                "body": body,
                "to_email": instance.email,
            }

            send_email_to_client(data)

        if not active_status and user and user.is_superuser :
            product_ids = instance.products.values_list('id', flat=True)
            if product_ids:
                Cart.objects.filter(product__in=product_ids).update(deleted_at=datetime.now())

        return super().update(
            instance,
            validated_data,
        )


class VendorCategoryDeleteSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["user", "category"]


class UserCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = [
            "id",
            "is_active",
            "is_staff",
            "full_name",
            "email",
            "phone",
            "is_vendor",
            "address",
            "is_buyer",
            "apartment_number",
            "street_name",
            "city",
            "state",
            "zip_code",
            "shop_name",
            "count",
            "status",
            "created_at",
        ]

    def create(self, validated_data):
        is_vendor = validated_data.get("is_vendor", False)
        is_buyer = validated_data.get("is_buyer", False)

        if is_vendor:
            validated_data["is_active"] = True
            validated_data["is_staff"] = True
            validated_data["is_vendor"] = True
            validated_data["otp_verified"] = True
        elif is_buyer:
            validated_data["is_active"] = True
            validated_data["is_buyer"] = True
            validated_data["otp_verified"] = True

        # Generate a random password
        password = "".join(random.choices(string.ascii_letters + string.digits, k=8))
        # Set and hash the password
        user = User(**validated_data)
        user.set_password(password)
        user.save()
        email = user.email
        subject = "Your  account credentials"
        body = f"""
            <p>Welcome to e360!</p>
            <p>Your login details are below. Please login and submit your documents:</p>
            <p>
                <strong>Email:</strong> {email}<br>
                <strong>Password:</strong> {password}
            </p>
            """
        html_content = '<a href="https://vendor.e360mart.com/sign-in/" target="_blank">Login URL</a>'
        full_message = f"{body}</br></br>{html_content}"

        data = {"subject": subject, "body": full_message, "to_email": email}

        send_email(data)

        return user


class ChangePasswordSer(serializers.Serializer):
    email = serializers.EmailField()
    old_password = serializers.CharField(max_length=128)
    password = serializers.CharField(max_length=128)
    confirm_password = serializers.CharField(max_length=128)


class VendorProductSer(serializers.Serializer):
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = User
        fields = "__all__"


class UserdataSer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "email", "full_name", "phone", "address", "image"]


class UserSer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "email",
            "full_name",
            "count",
            "is_superuser",
            "is_buyer",
            "is_vendor",
            "lat",
            "long",
            "location",
            "image",
            "status",
            "shop_name",
            "phone",
            "address",
        ]


class UserDeletionSerializer(serializers.Serializer):
    email = serializers.EmailField()


class UserSerProduct(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "lat", "long"]


class RegisterSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(required=True)
    phone = serializers.CharField(required=True)
    full_name = serializers.CharField(required=True)
    sso_id = serializers.CharField(required=True)

    class Meta:
        model = User
        fields = [
            "username",
            "sso_id",
            "email",
            "phone",
            "full_name",
            "is_buyer",
            "is_vendor",
            "referral_code",
            "referred_by"
        ]

    def create(self, validated_data):
        user = User(**validated_data)
        user.sso_status = True
        user.save()
        return user
