from decimal import Decimal, ROUND_HALF_UP
from rest_framework import serializers
from .models import BankAccount, WithdrawalDeductionConfig, WithdrawalRequest


class WithdrawalDeductionConfigSerializer(serializers.ModelSerializer):
    total_deduction_percent = serializers.DecimalField(read_only=True, max_digits=8, decimal_places=3)

    class Meta:
        model = WithdrawalDeductionConfig
        fields = [
            'id',
            'name',
            'tds_percent',
            'repurchase_percent',
            'welfare_fund_percent',
            'technology_charges_percent',
            'operations_charges_percent',
            'total_deduction_percent',
            'is_active',
            'created_at',
            'updated_at',
        ]
        read_only_fields = ['id', 'total_deduction_percent', 'created_at', 'updated_at']

    def validate_tds_percent(self, value):
        if value < 0 or value > 100:
            raise serializers.ValidationError('TDS percent must be between 0 and 100.')
        return value

    def validate_repurchase_percent(self, value):
        if value < 0 or value > 100:
            raise serializers.ValidationError('Repurchase percent must be between 0 and 100.')
        return value

    def validate_welfare_fund_percent(self, value):
        if value < 0 or value > 100:
            raise serializers.ValidationError('Welfare fund percent must be between 0 and 100.')
        return value

    def validate_technology_charges_percent(self, value):
        if value < 0 or value > 100:
            raise serializers.ValidationError('Technology charges percent must be between 0 and 100.')
        return value

    def validate_operations_charges_percent(self, value):
        if value < 0 or value > 100:
            raise serializers.ValidationError('Operations/Admin charges percent must be between 0 and 100.')
        return value

    def validate(self, attrs):
        from decimal import Decimal
        total = sum(Decimal(str(attrs.get(f, 0))) for f in [
            'tds_percent', 'repurchase_percent', 'welfare_fund_percent',
            'technology_charges_percent', 'operations_charges_percent',
        ])
        if total > 100:
            raise serializers.ValidationError('Total deduction percent cannot exceed 100%.')
        return attrs


class BankAccountSerializer(serializers.ModelSerializer):
    masked_account_number = serializers.CharField(read_only=True)

    class Meta:
        model = BankAccount
        fields = [
            'id',
            'account_holder_name',
            'account_number',
            'masked_account_number',
            'ifsc_code',
            'bank_name',
            'is_verified',
            'is_primary',
            'created_at',
        ]
        read_only_fields = ['id', 'is_verified', 'created_at', 'masked_account_number']
        extra_kwargs = {
            'account_number': {'write_only': True},
        }


class BankAccountMinimalSerializer(serializers.ModelSerializer):
    masked_account_number = serializers.CharField(read_only=True)

    class Meta:
        model = BankAccount
        fields = ['id', 'bank_name', 'masked_account_number', 'ifsc_code', 'is_verified', 'is_primary']


class WithdrawalRequestSerializer(serializers.ModelSerializer):
    bank_account = BankAccountMinimalSerializer(read_only=True)
    deduction_breakdown = serializers.SerializerMethodField()

    class Meta:
        model = WithdrawalRequest
        fields = [
            'id',
            'user',
            'bank_account',
            'amount_requested',
            'tds_amount',
            'admin_fee_amount',
            'processing_fee_amount',
            'total_deduction_amount',
            'net_amount',
            'deduction_config',
            'status',
            'reference_id',
            'created_at',
                'processed_at',
                'remarks',
                'source',
                'upstream_gross_amount',
                'deduction_breakdown',
        ]
        read_only_fields = [
            'id',
            'user',
            'bank_account',
            'tds_amount',
            'admin_fee_amount',
            'processing_fee_amount',
            'total_deduction_amount',
            'net_amount',
            'deduction_config',
            'status',
            'reference_id',
            'created_at',
            'processed_at',
        ]

    def get_deduction_breakdown(self, obj):
        return _build_deduction_breakdown(obj)


class AdminWithdrawalRequestSerializer(serializers.ModelSerializer):
    user_name = serializers.SerializerMethodField()
    user_mobile = serializers.SerializerMethodField()
    bank_account = BankAccountMinimalSerializer(read_only=True)
    deduction_breakdown = serializers.SerializerMethodField()

    class Meta:
        model = WithdrawalRequest
        fields = [
            'id',
            'user',
            'user_name',
            'user_mobile',
            'bank_account',
            'amount_requested',
            'tds_amount',
            'admin_fee_amount',
            'processing_fee_amount',
            'total_deduction_amount',
            'net_amount',
            'status',
            'reference_id',
            'created_at',
                'processed_at',
                'remarks',
                'source',
                'upstream_gross_amount',
                'deduction_breakdown',
        ]

    def get_user_name(self, obj):
        u = obj.user
        full = f"{getattr(u, 'first_name', '')} {getattr(u, 'last_name', '')}".strip()
        return full or getattr(u, 'email', '') or str(u)

    def get_user_mobile(self, obj):
        u = obj.user
        return getattr(u, 'mobile', None) or getattr(u, 'phone_number', None) or ""

    def get_deduction_breakdown(self, obj):
        return _build_deduction_breakdown(obj)


def _build_deduction_breakdown(obj):
    config = getattr(obj, 'deduction_config', None)
    if not config:
        return None

    base_amount = Decimal(str(obj.upstream_gross_amount or obj.amount_requested or '0'))
    if base_amount <= 0:
        return None

    def pct_amount(percent):
        return (base_amount * Decimal(str(percent)) / Decimal('100')).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)

    tds_amount = pct_amount(config.tds_percent)
    repurchase_amount = pct_amount(config.repurchase_percent)
    welfare_amount = pct_amount(config.welfare_fund_percent)
    technology_amount = pct_amount(config.technology_charges_percent)
    operations_amount = pct_amount(config.operations_charges_percent)
    total_amount = (tds_amount + repurchase_amount + welfare_amount + technology_amount + operations_amount).quantize(
        Decimal('0.01'), rounding=ROUND_HALF_UP
    )

    return {
        'base_amount': str(base_amount),
        'tds_amount': str(tds_amount),
        'repurchase_amount': str(repurchase_amount),
        'welfare_amount': str(welfare_amount),
        'technology_amount': str(technology_amount),
        'operations_amount': str(operations_amount),
        'total_amount': str(total_amount),
        'tds_percent': str(config.tds_percent),
        'repurchase_percent': str(config.repurchase_percent),
        'welfare_percent': str(config.welfare_fund_percent),
        'technology_percent': str(config.technology_charges_percent),
        'operations_percent': str(config.operations_charges_percent),
    }

