# shop_management/serializers/data/advance.py
from decimal import Decimal
from rest_framework import serializers
from shop_management.serializers.data.base import DataRootSerializer
from shop_management.models.data.account_transaction import (
    AccountTransaction,
    AccountTransactionType,
)
from shop_management.models.data.advance import Advance


class AdvanceSerializer(DataRootSerializer):
    employee_details = serializers.SerializerMethodField()
    shop_details = serializers.SerializerMethodField()
    currency_details = serializers.SerializerMethodField()
    account_details = serializers.SerializerMethodField()

    class Meta:
        model = Advance
        fields = "__all__"
        read_only_fields = ["converted_amount"]

    def get_employee_details(self, obj):
        if obj.employee:
            return {
                "name": obj.employee.name,
                "contact": obj.employee.contact,
                "salary": obj.employee.salary,
            }
        else:
            return None

    def get_shop_details(self, obj):
        if obj.employee and hasattr(obj.employee, "shop"):
            return {"id": obj.employee.shop.id, "name": obj.employee.shop.name}
        return None  # Avoid AttributeError

    def get_currency_details(self, obj):
        if obj.currency:
            return {
                "id": obj.currency.id,
                "title": obj.currency.title,
                "shop": obj.currency.shop_id,
            }
        return None

    def get_account_details(self, obj):
        if obj.account:
            return {
                "id": obj.account.id,
                "name": obj.account.name,
                "currency_id": obj.account.currency_id,
                "currency_title": obj.account.currency.title if obj.account.currency else None,
            }
        return None

    @staticmethod
    def _advance_ref_prefix(advance):
        return f"Advance #{advance.id}"

    def _sync_account_transaction(self, advance):
        ref_prefix = self._advance_ref_prefix(advance)
        AccountTransaction.objects.filter(description__startswith=ref_prefix).delete()
        AccountTransaction.objects.create(
            account=advance.account,
            account_currency=advance.account.currency,
            transaction_currency=advance.currency,
            transaction_type=AccountTransactionType.DEBIT,
            amount=advance.amount,
            exchange_rate=advance.exchange_rate,
            converted_amount=advance.converted_amount,
            description=(
                f"{ref_prefix} for {advance.employee.name if advance.employee else 'Unknown Employee'}"
                f"{f' | Notes: {advance.notes}' if advance.notes else ''}"
            ),
            transaction_date=advance.payment_date.date(),
        )

    def validate(self, attrs):
        employee = attrs.get("employee") or getattr(self.instance, "employee", None)
        currency = attrs.get("currency") or getattr(self.instance, "currency", None)
        account = attrs.get("account") or getattr(self.instance, "account", None)
        amount = attrs.get("amount") or getattr(self.instance, "amount", None)
        manual_rate = attrs.get("exchange_rate")

        if not employee:
            raise serializers.ValidationError({"employee": "Employee is required."})
        if not currency:
            raise serializers.ValidationError({"currency": "Currency is required."})
        if account is None:
            raise serializers.ValidationError({"account": "Account is required."})
        if not amount or amount <= 0:
            raise serializers.ValidationError({"amount": "Amount must be greater than 0."})
        if currency.shop_id != employee.shop_id:
            raise serializers.ValidationError(
                {"currency": "Currency must belong to the employee shop."}
            )
        if account.shop_id != employee.shop_id:
            raise serializers.ValidationError(
                {"account": "Selected account must belong to the employee shop."}
            )

        resolved_rate = manual_rate or AccountTransaction.resolve_exchange_rate(
            employee.shop, currency.id, account.currency_id
        )
        if resolved_rate is None:
            raise serializers.ValidationError(
                {"account": "No exchange rate found between advance currency and account currency."}
            )
        if resolved_rate <= 0:
            raise serializers.ValidationError(
                {"exchange_rate": "Exchange rate must be greater than 0."}
            )

        attrs["exchange_rate"] = Decimal(resolved_rate)
        attrs["converted_amount"] = AccountTransaction.compute_converted_amount(
            Decimal(amount), Decimal(resolved_rate)
        )
        return attrs

    def create(self, validated_data):
        advance = super().create(validated_data)
        self._sync_account_transaction(advance)
        return advance

    def update(self, instance, validated_data):
        advance = super().update(instance, validated_data)
        self._sync_account_transaction(advance)
        return advance
