"""
Deposit approval side-effect services.
"""
from decimal import Decimal

from django.utils import timezone

from referrals.services import apply_referral_rewards_for_approved_deposit, reverse_referral_rewards_for_deposit
from signals.services import activate_signal_plan_for_approved_deposit, cancel_signal_plan_for_deposit
from wallet.models import Transaction, TransactionStatus, TransactionType, Wallet


def apply_deposit_approval_effects(deposit):
    """
    Credit the approved deposit and trigger referral rewards.
    """
    wallet, created = Wallet.objects.get_or_create(user=deposit.user)
    wallet.balance += deposit.amount
    wallet.total_deposits += deposit.amount
    wallet.save()

    transaction, created = Transaction.objects.get_or_create(
        wallet=wallet,
        transaction_type=TransactionType.DEPOSIT,
        reference_id=f'DEP-{deposit.id}',
        defaults={
            'amount': deposit.amount,
            'status': TransactionStatus.COMPLETED,
            'description': f'Deposit #{deposit.id} approved',
            'completed_at': timezone.now(),
        },
    )

    if not created:
        transaction.amount = deposit.amount
        transaction.status = TransactionStatus.COMPLETED
        transaction.description = f'Deposit #{deposit.id} approved'
        transaction.completed_at = timezone.now()
        transaction.save()

    apply_referral_rewards_for_approved_deposit(deposit)
    activate_signal_plan_for_approved_deposit(deposit)


def reverse_deposit_approval_effects(deposit):
    """
    Remove the approved deposit effects when approval is reverted.
    """
    wallet = Wallet.objects.get(user=deposit.user)
    wallet.balance -= deposit.amount
    wallet.total_deposits -= deposit.amount

    if wallet.balance < 0:
        wallet.balance = Decimal('0.00')
    if wallet.total_deposits < 0:
        wallet.total_deposits = Decimal('0.00')

    wallet.save()

    Transaction.objects.filter(
        wallet=wallet,
        transaction_type=TransactionType.DEPOSIT,
        reference_id=f'DEP-{deposit.id}',
    ).update(
        status=TransactionStatus.CANCELLED,
        completed_at=timezone.now(),
        description=f'Deposit #{deposit.id} approval reversed',
    )

    reverse_referral_rewards_for_deposit(deposit)
    cancel_signal_plan_for_deposit(deposit)
