from rest_framework import serializers
from django.core.mail import EmailMultiAlternatives
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from django.core.mail import send_mail
from django.conf import settings

from .models import Module, Permission, Role, PermissionRole, Admin, Master, Banner, Gift, AppSetting, FemaleReward

class ModuleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Module
        fields = '__all__'


class PermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = '__all__'


class PermissionRoleSerializer(serializers.ModelSerializer):
    class Meta:
        model = PermissionRole
        fields = '__all__'


class RoleSerializer(serializers.ModelSerializer):
    permissions = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Permission.objects.all(),
        required=False
    )

    class Meta:
        model = Role
        fields = '__all__'

    def create(self, validated_data):
        permissions_data = validated_data.pop('permissions', [])
        role = Role.objects.create(**validated_data)
        role.permissions.set(permissions_data)
        return role

    def update(self, instance, validated_data):
        permissions_data = validated_data.pop('permissions', None)

        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        if permissions_data is not None:
            instance.permissions.set(permissions_data)

        return instance


class AdminSerializer(serializers.ModelSerializer):
    class Meta:
        model = Admin
        fields = '__all__'
        extra_kwargs = {
            'password': {'write_only': True}
        }

    def create(self, validated_data):
        password = validated_data.get('password')
        name = validated_data.get('name')
        email = validated_data.get('email')

        user, created = User.objects.get_or_create(username=name, defaults={'email': email})
        if created:
            user.set_password(password)
            user.save()
        else:
            updated = False
            if password:
                user.set_password(password)
                updated = True
            if email and user.email != email:
                user.email = email
                updated = True
            if updated:
                user.save()

        if password:
            validated_data['password'] = make_password(password)

        admin = super().create(validated_data)
        return admin

class AdminUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Admin
        exclude = ['password','admin_code']


class AdminStatusUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Admin
        fields = ['status']


class MasterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Master
        fields = ['id', 'type', 'name', 'value1', 'status', 'created_at', 'updated_at']


class MasterStatusUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Master
        fields = ['status']

class AdminLoginSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField(write_only=True)

    def validate(self, data):
        email = data.get('email')
        password = data.get('password')

        try:
            admin = Admin.objects.get(email=email)
        except Admin.DoesNotExist:
            raise serializers.ValidationError("Invalid credentials")

        if not check_password(password, admin.password):
            raise serializers.ValidationError("Invalid credentials")

        data['admin'] = admin
        return data
    
    
class AdminRequestPasswordResetSerializer(serializers.Serializer):
    email = serializers.EmailField()

    def validate_email(self, value):
        if not Admin.objects.filter(email=value).exists():
            raise serializers.ValidationError("No admin found with this email.")
        return value

    def save(self):
        email = self.validated_data['email']
        admin = Admin.objects.get(email=email)
        from django.contrib.auth.models import User

        try:
            user = User.objects.get(username=admin.name)
        except User.DoesNotExist:
            return

        uid = urlsafe_base64_encode(force_bytes(user.pk))
        token = default_token_generator.make_token(user)

        reset_url = f"{settings.FRONTEND_URL}/resetpassword?uid={uid}&token={token}&email={email}"

        subject = "Admin Password Reset"
        from_email = settings.DEFAULT_FROM_EMAIL
        recipient_list = [email]

        text_content = f"Click the link below to reset your password:\n\n{reset_url}"
        html_content = f"""
            <p>Click the link below to reset your password:</p>
            <p><a href="{reset_url}">{reset_url}</a></p>
        """

        msg = EmailMultiAlternatives(subject, text_content, from_email, recipient_list)
        msg.attach_alternative(html_content, "text/html")
        msg.send()

class AdminConfirmResetPasswordSerializer(serializers.Serializer):
    uid = serializers.CharField()
    token = serializers.CharField()
    new_password = serializers.CharField(min_length=6)

    def validate(self, data):
        try:
            uid = urlsafe_base64_decode(data['uid']).decode()
            self.user = User.objects.get(pk=uid)
        except Exception:
            raise serializers.ValidationError("Invalid UID")

        if not default_token_generator.check_token(self.user, data['token']):
            raise serializers.ValidationError("Invalid or expired token")

        return data

    def save(self):
        password = self.validated_data['new_password']
        self.user.set_password(password)
        self.user.save()

        try:
            admin = Admin.objects.get(name=self.user.username)
            admin.password = make_password(password)
            admin.save()
        except Admin.DoesNotExist:
            pass


class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = '__all__'

class BannerStatusSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ('status',)

class BannerImageTypeUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ['type', 'image']

#settings file
class GiftSerializer(serializers.ModelSerializer):
    class Meta:
        model = Gift
        fields = '__all__'


class AppSettingSerializer(serializers.ModelSerializer):
    class Meta:
        model = AppSetting
        fields = ['id', 'name', 'code', 'value', 'notes', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']


class FemaleRewardSerializer(serializers.ModelSerializer):
    duration = serializers.SerializerMethodField()

    class Meta:
        model = FemaleReward
        fields = '__all__'

    def get_duration(self, obj):
        return f"{obj.start_min} - {obj.end_min}"
    
class FemaleRewardInputSerializer(serializers.Serializer):
    Duration = serializers.CharField()
    Type = serializers.ChoiceField(choices=[("1", "Audio"), ("2", "Video")])
    Normal = serializers.FloatField()
    Premium = serializers.FloatField()

    def validate_Duration(self, value):
        try:
            start, end = value.split("-")
            return float(start.strip()), float(end.strip())
        except Exception:
            raise serializers.ValidationError("Invalid duration format. Expected 'start - end'.")

class FemaleRewardCustomSerializer(serializers.Serializer):
    Type = serializers.IntegerField()
    Duration = serializers.CharField()
    Normal = serializers.FloatField(required=False, allow_null=True)
    Premium = serializers.FloatField(required=False, allow_null=True)
    Normal_id = serializers.IntegerField(required=False, allow_null=True)
    Premium_id = serializers.IntegerField(required=False, allow_null=True)

    def to_representation(self, instance):
        return {
            "Type": instance.type,
            "Duration": f"{instance.start_min} - {instance.end_min}",
            "Normal": instance.coins if instance.user_type == 1 else None,
            "Premium": instance.coins if instance.user_type == 2 else None,
            "Normal_id": instance.id if instance.user_type == 1 else None,
            "Premium_id": instance.id if instance.user_type == 2 else None,
        }

    def update(self, instance, validated_data):
        start_min, end_min = map(float, validated_data["Duration"].split("-"))
        instance.type = validated_data["Type"]
        instance.start_min = start_min
        instance.end_min = end_min

        if validated_data.get("Normal") is not None:
            instance.coins = validated_data["Normal"]
            instance.user_type = 1
        elif validated_data.get("Premium") is not None:
            instance.coins = validated_data["Premium"]
            instance.user_type = 2

        instance.save()
        return instance
    

class AdminRejectUserSerializer(serializers.Serializer):
    user_id = serializers.IntegerField()
    reject_reason = serializers.CharField(max_length=255)