import logging
from decimal import Decimal

from django.db.models import Sum, Value, DecimalField, Case, When, F
from django.db.models.functions import Coalesce

from apps.transactions.models import (
    Transaction,
)

logger = logging.getLogger(__name__)


class TransactionsGetter:
    def __init__(self, **filters):
        self.__queryset = Transaction.objects.filter(**filters)

    def exclude(self, **exclude_filters):
        self.__queryset = self.__queryset.exclude(**exclude_filters)

        return self

    @property
    def sum(self):
        return self.__queryset.aggregate(
            total=Coalesce(
                Sum("amount"), Value(Decimal("0")), output_field=DecimalField()
            )
        )["total"]

    @property
    def balance(self):
        return abs(
            self.__queryset.aggregate(
                balance=Coalesce(
                    Sum(
                        Case(
                            When(type=Transaction.Type.EXPENSE, then=-F("amount")),
                            default=F("amount"),
                            output_field=DecimalField(),
                        )
                    ),
                    Value(Decimal("0")),
                    output_field=DecimalField(),
                )
            )["balance"]
        )

    @property
    def raw_balance(self):
        return self.__queryset.aggregate(
            balance=Coalesce(
                Sum(
                    Case(
                        When(type=Transaction.Type.EXPENSE, then=-F("amount")),
                        default=F("amount"),
                        output_field=DecimalField(),
                    )
                ),
                Value(Decimal("0")),
                output_field=DecimalField(),
            )
        )["balance"]


def serialize_transaction(sender: Transaction, deleted: bool):
    return {
        "id": sender.id,
        "account": (sender.account.id, sender.account.name),
        "account_group": (
            sender.account.group.id if sender.account.group else None,
            sender.account.group.name if sender.account.group else None,
        ),
        "type": str(sender.type),
        "is_paid": sender.is_paid,
        "is_asset": sender.account.is_asset,
        "is_archived": sender.account.is_archived,
        "category": (
            sender.category.id if sender.category else None,
            sender.category.name if sender.category else None,
        ),
        "date": sender.date.isoformat(),
        "reference_date": sender.reference_date.isoformat(),
        "amount": str(sender.amount),
        "description": sender.description,
        "notes": sender.notes,
        "tags": list(sender.tags.values_list("id", "name")),
        "entities": list(sender.entities.values_list("id", "name")),
        "deleted": deleted,
        "internal_note": sender.internal_note,
        "internal_id": sender.internal_id,
        "mute": sender.mute,
        "installment_id": sender.installment_id if sender.installment_plan else None,
        "installment_total": (
            sender.installment_plan.number_of_installments
            if sender.installment_plan is not None
            else None
        ),
        "installment": sender.installment_plan is not None,
        "recurring_transaction": sender.recurring_transaction is not None,
    }
