from rest_framework import serializers
from .models import BalanceTransfer
from django.contrib.auth import get_user_model
from decimal import Decimal
from django.db import transaction
from django.db.models import F

User = get_user_model()

class BalanceTransferSerializer(serializers.ModelSerializer):
    receiver_email = serializers.EmailField(write_only=True)
    sender_name = serializers.ReadOnlyField(source='sender.user.name')
    receiver_name = serializers.ReadOnlyField(source='receiver.user.name')
    is_sent = serializers.SerializerMethodField()

    class Meta:
        model = BalanceTransfer
        fields = ['id', 'receiver_email', 'sender_name', 'receiver_name', 'is_sent', 'amount', 'fee', 'timestamp']
        read_only_fields = ['id', 'fee', 'timestamp', 'is_sent']

    def get_is_sent(self, obj):
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            return obj.sender.user == request.user
        return False

    def validate(self, data):
        request = self.context.get('request')
        sender_profile = request.user.profile
        input_amount = Decimal(str(data.get('amount'))) # ইউজার যত টাকা লিখেছে
        receiver_email = data.get('receiver_email')

        # ১. মিনিমাম অ্যামাউন্ট চেক
        if input_amount < Decimal('2.00'):
            raise serializers.ValidationError({"amount": "Minimum transfer amount is $2.00."})

        # ২. নিজেকে নিজে পাঠানো চেক
        if request.user.email == receiver_email:
            raise serializers.ValidationError({"receiver_email": "You cannot transfer to yourself."})

        # ৩. পর্যাপ্ত ব্যালেন্স আছে কিনা চেক
        if sender_profile.balance < input_amount:
            raise serializers.ValidationError({"amount": "Insufficient balance."})

        # ৪. রিসিভার ইমেইল দিয়ে প্রোফাইল খুঁজে বের করা
        try:
            receiver_user = User.objects.get(email=receiver_email)
            receiver_profile = receiver_user.profile
        except User.DoesNotExist:
            raise serializers.ValidationError({"receiver_email": "User with this email not found."})

        # ৫. ক্যালকুলেশন
        fee = (input_amount * Decimal('7')) / Decimal('100')
        net_amount = input_amount - fee

        # ডেটা ডিকশনারিতে ভ্যালুগুলো সেট করা
        data['receiver'] = receiver_profile
        data['fee'] = fee
        data['amount'] = net_amount 
        data['total_to_deduct'] = input_amount # সেন্ডারের মেইন ব্যালেন্স থেকে পুরোটা কাটবে

        return data

    @transaction.atomic
    def create(self, validated_data):
        # ভ্যালিডেশন থেকে ডাটা নেওয়া
        total_to_deduct = validated_data.pop('total_to_deduct')
        receiver_profile = validated_data['receiver']
        sender_profile = validated_data['sender'] # ViewSet থেকে আসবে
        net_amount = validated_data['amount']

        # ডাটাবেসে ব্যালেন্স আপডেট করা (F expression ensures accuracy)
        # সেন্ডারের প্রোফাইল থেকে টাকা কমানো
        sender_profile.__class__.objects.filter(id=sender_profile.id).update(
            balance=F('balance') - total_to_deduct
        )
        
        # রিসিভারের প্রোফাইলে টাকা বাড়ানো
        receiver_profile.__class__.objects.filter(id=receiver_profile.id).update(
            balance=F('balance') + net_amount
        )

        # receiver_email মডেলে নেই, তাই পপ করে দিন
        validated_data.pop('receiver_email', None)

        # ফাইনাল ট্রান্সফার রেকর্ড সেভ
        return super().create(validated_data)