# =====================================================
# TEACHER PAYSLIP SERIALIZERS
# =====================================================

from rest_framework import serializers
from payslips.models import MonthlyPaySlip, PaymentTransaction, TeacherPayStructure
from people.models import Teacher
from django.db.models import Q, Count, Sum


class TeacherPaySlipListSerializer(serializers.ModelSerializer):
    """List view serializer for teacher pay slips"""

    month_name = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    total_paid = serializers.SerializerMethodField()
    remaining_balance = serializers.SerializerMethodField()
    display_period = serializers.SerializerMethodField()

    class Meta:
        model = MonthlyPaySlip
        fields = [
            "id",
            "pay_slip_number",
            "month",
            "month_name",
            "year",
            "display_period",
            "status",
            "status_display",
            "net_pay",
            "total_paid",
            "remaining_balance",
            "is_acknowledged",
            "created_at",
        ]

    def get_month_name(self, obj):
        months = [
            "January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December",
        ]
        return months[obj.month - 1] if 1 <= obj.month <= 12 else str(obj.month)

    def get_display_period(self, obj):
        """Return formatted period like 'April 2026'"""
        return f"{self.get_month_name(obj)} {obj.year}"

    def get_status_display(self, obj):
        status_map = {
            "DRAFT": "Draft",
            "PENDING": "Pending Approval",
            "APPROVED": "Approved",
            "PAID": "Paid",
            "CANCELLED": "Cancelled",
        }
        return status_map.get(obj.status, obj.status)

    def get_total_paid(self, obj):
        total = obj.payment_transactions.filter(status="COMPLETED").aggregate(
            total=Sum("amount")
        )["total"]
        return float(total) if total else 0

    def get_remaining_balance(self, obj):
        total_paid = self.get_total_paid(obj)
        net_pay = float(obj.net_pay)
        remaining = net_pay - total_paid
        return round(max(remaining, 0), 2)


class TeacherPaySlipDetailSerializer(serializers.ModelSerializer):
    """Detail view serializer for teacher pay slips with full details"""

    month_name = serializers.SerializerMethodField()
    status_display = serializers.SerializerMethodField()
    total_paid = serializers.SerializerMethodField()
    remaining_balance = serializers.SerializerMethodField()
    payment_transactions = serializers.SerializerMethodField()

    # Earnings breakdown
    total_allowances = serializers.SerializerMethodField()
    total_incentives = serializers.SerializerMethodField()
    total_deductions = serializers.SerializerMethodField()

    class Meta:
        model = MonthlyPaySlip
        fields = [
            "id",
            "pay_slip_number",
            "month",
            "month_name",
            "year",
            "status",
            "status_display",
            "base_salary",
            "dearness_allowance",
            "house_rent_allowance",
            "city_compensatory_allowance",
            "travel_allowance",
            "medical_allowance",
            "special_allowance",
            "education_allowance",
            "telephone_allowance",
            "performance_incentive",
            "special_class_incentive",
            "subject_expert_incentive",
            "leadership_allowance",
            "festival_bonus",
            "annual_bonus",
            "overtime_allowance",
            "variable_pay",
            "additional_earnings",
            "other_allowances",
            "provident_fund_employee",
            "provident_fund_employer",
            "esi_deduction",
            "professional_tax",
            "income_tax",
            "loan_deduction",
            "advance_deduction",
            "attendance_deduction",
            "other_deductions",
            "total_allowances",
            "total_incentives",
            "total_deductions",
            "total_earnings",
            "net_pay",
            "total_paid",
            "remaining_balance",
            "payment_transactions",
            "casual_leave_taken",
            "sick_leave_taken",
            "earned_leave_taken",
            "unpaid_leave_days",
            "total_working_days",
            "days_present",
            "days_absent",
            "late_days",
            "remarks",
            "hr_remarks",
            "is_acknowledged",
            "acknowledged_at",
            "created_at",
        ]

    def get_month_name(self, obj):
        months = [
            "January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December",
        ]
        return months[obj.month - 1] if 1 <= obj.month <= 12 else str(obj.month)

    def get_status_display(self, obj):
        status_map = {
            "DRAFT": "Draft",
            "PENDING": "Pending Approval",
            "APPROVED": "Approved",
            "PAID": "Paid",
            "CANCELLED": "Cancelled",
        }
        return status_map.get(obj.status, obj.status)

    def get_total_paid(self, obj):
        total = obj.payment_transactions.filter(status="COMPLETED").aggregate(
            total=Sum("amount")
        )["total"]
        return float(total) if total else 0

    def get_remaining_balance(self, obj):
        total_paid = self.get_total_paid(obj)
        net_pay = float(obj.net_pay)
        remaining = net_pay - total_paid
        return round(max(remaining, 0), 2)

    def get_payment_transactions(self, obj):
        # REMOVED: .filter(is_active=True) - PaymentTransaction doesn't have is_active field
        transactions = obj.payment_transactions.all().order_by("-payment_date")
        return TeacherPaymentTransactionSerializer(transactions, many=True).data

    def get_total_allowances(self, obj):
        total = 0
        total += float(obj.dearness_allowance or 0)
        total += float(obj.house_rent_allowance or 0)
        total += float(obj.city_compensatory_allowance or 0)
        total += float(obj.travel_allowance or 0)
        total += float(obj.medical_allowance or 0)
        total += float(obj.special_allowance or 0)
        total += float(obj.education_allowance or 0)
        total += float(obj.telephone_allowance or 0)
        return round(total, 2)

    def get_total_incentives(self, obj):
        total = 0
        total += float(obj.performance_incentive or 0)
        total += float(obj.special_class_incentive or 0)
        total += float(obj.subject_expert_incentive or 0)
        total += float(obj.leadership_allowance or 0)
        total += float(obj.festival_bonus or 0)
        total += float(obj.annual_bonus or 0)
        total += float(obj.overtime_allowance or 0)
        total += float(obj.variable_pay or 0)
        total += float(obj.additional_earnings or 0)
        return round(total, 2)

    def get_total_deductions(self, obj):
        total = 0
        total += float(obj.provident_fund_employee or 0)
        total += float(obj.esi_deduction or 0)
        total += float(obj.professional_tax or 0)
        total += float(obj.income_tax or 0)
        total += float(obj.loan_deduction or 0)
        total += float(obj.advance_deduction or 0)
        total += float(obj.attendance_deduction or 0)
        # Add other deductions from JSON if needed
        if obj.other_deductions:
            total += sum(obj.other_deductions.values())
        return round(total, 2)


class TeacherPaymentTransactionSerializer(serializers.ModelSerializer):
    """Serializer for payment transactions in teacher view"""

    payment_method_display = serializers.CharField(
        source="get_payment_method_display", read_only=True
    )
    payment_type_display = serializers.CharField(
        source="get_payment_type_display", read_only=True
    )
    status_display = serializers.CharField(source="get_status_display", read_only=True)

    class Meta:
        model = PaymentTransaction
        fields = [
            "id",
            "amount",
            "payment_type",
            "payment_type_display",
            "payment_method",
            "payment_method_display",
            "payment_date",
            "transaction_id",
            "status",
            "status_display",
            "remarks",
        ]


class TeacherPaySlipSummarySerializer(serializers.Serializer):
    """Serializer for teacher pay slip summary"""

    total_pay_slips = serializers.IntegerField()
    total_earned = serializers.DecimalField(max_digits=15, decimal_places=2)
    total_deductions = serializers.DecimalField(max_digits=15, decimal_places=2)
    average_monthly = serializers.DecimalField(max_digits=15, decimal_places=2)
    best_month = serializers.DictField()
    worst_month = serializers.DictField()
    yearly_breakdown = serializers.ListField()
    monthly_data = serializers.ListField()


class TeacherCurrentPayStructureSerializer(serializers.ModelSerializer):
    """Serializer for teacher's current pay structure"""

    teacher_name = serializers.CharField(source="teacher.full_name", read_only=True)
    total_monthly_earnings = serializers.SerializerMethodField()

    class Meta:
        model = TeacherPayStructure
        fields = [
            "id",
            "teacher",
            "teacher_name",
            "base_salary",
            "dearness_allowance",
            "house_rent_allowance",
            "city_compensatory_allowance",
            "travel_allowance",
            "medical_allowance",
            "special_allowance",
            "education_allowance",
            "telephone_allowance",
            "default_performance_incentive",
            "default_special_class_incentive",
            "default_subject_expert_incentive",
            "default_leadership_allowance",
            "provident_fund_percentage",
            "esi_percentage",
            "professional_tax_fixed",
            "total_monthly_earnings",
            "effective_from",
            "effective_to",
            "is_active",
        ]

    def get_total_monthly_earnings(self, obj):
        total = float(obj.base_salary or 0)
        total += float(obj.dearness_allowance or 0)
        total += float(obj.house_rent_allowance or 0)
        total += float(obj.city_compensatory_allowance or 0)
        total += float(obj.travel_allowance or 0)
        total += float(obj.medical_allowance or 0)
        total += float(obj.special_allowance or 0)
        total += float(obj.education_allowance or 0)
        total += float(obj.telephone_allowance or 0)
        total += float(obj.default_performance_incentive or 0)
        total += float(obj.default_special_class_incentive or 0)
        total += float(obj.default_subject_expert_incentive or 0)
        total += float(obj.default_leadership_allowance or 0)
        return round(total, 2)
