# -*- coding: utf-8 -*-
"""
Тесты для вычисления баланса кошелька.

Используем TenantTestCase для корректной работы с tenant-системой.
"""
from decimal import Decimal

from django.core.cache import cache
from django_tenants.test.cases import TenantTestCase

from customers.models import Customer, WalletTransaction


class WalletBalanceCalculationTestCase(TenantTestCase):
    """Тесты вычисления баланса кошелька из транзакций."""

    def setUp(self):
        """Создаём тестового клиента и очищаем кеш."""
        self.customer = Customer.objects.create(name="Тестовый клиент")
        cache.clear()

    def tearDown(self):
        """Очищаем кеш после каждого теста."""
        cache.clear()

    def test_empty_wallet_returns_zero(self):
        """Пустой кошелёк должен возвращать 0."""
        self.assertEqual(self.customer.wallet_balance, Decimal('0'))

    def test_single_deposit(self):
        """Одно пополнение корректно учитывается."""
        WalletTransaction.objects.create(
            customer=self.customer,
            signed_amount=Decimal('100.00'),
            transaction_type='deposit',
            balance_category='money'
        )
        cache.clear()
        self.assertEqual(self.customer.wallet_balance, Decimal('100.00'))

    def test_single_spend(self):
        """Списание корректно учитывается (отрицательная сумма)."""
        # Сначала пополняем
        WalletTransaction.objects.create(
            customer=self.customer,
            signed_amount=Decimal('100.00'),
            transaction_type='deposit',
            balance_category='money'
        )
        # Затем списываем
        WalletTransaction.objects.create(
            customer=self.customer,
            signed_amount=Decimal('-30.00'),
            transaction_type='spend',
            balance_category='money'
        )
        cache.clear()
        self.assertEqual(self.customer.wallet_balance, Decimal('70.00'))

    def test_multiple_operations(self):
        """Несколько операций подряд вычисляются корректно."""
        operations = [
            ('deposit', Decimal('200.00')),
            ('spend', Decimal('-50.00')),
            ('deposit', Decimal('100.00')),
            ('spend', Decimal('-80.00')),
            ('adjustment', Decimal('10.00')),
        ]

        for txn_type, signed_amount in operations:
            WalletTransaction.objects.create(
                customer=self.customer,
                signed_amount=signed_amount,
                transaction_type=txn_type,
                balance_category='money'
            )

        cache.clear()
        # 200 - 50 + 100 - 80 + 10 = 180
        self.assertEqual(self.customer.wallet_balance, Decimal('180.00'))

    def test_amount_property_returns_absolute(self):
        """Property amount возвращает абсолютное значение."""
        txn = WalletTransaction.objects.create(
            customer=self.customer,
            signed_amount=Decimal('-50.00'),
            transaction_type='spend',
            balance_category='money'
        )
        self.assertEqual(txn.amount, Decimal('50.00'))

    def test_cache_invalidation(self):
        """Кеш инвалидируется методом invalidate_wallet_cache."""
        # Первый вызов - баланс 0
        self.assertEqual(self.customer.wallet_balance, Decimal('0'))

        # Добавляем транзакцию напрямую (без сервиса)
        WalletTransaction.objects.create(
            customer=self.customer,
            signed_amount=Decimal('100.00'),
            transaction_type='deposit',
            balance_category='money'
        )

        # Без инвалидации кеша - всё ещё 0 (закешировано)
        self.assertEqual(self.customer.get_wallet_balance(use_cache=True), Decimal('0'))

        # После инвалидации - 100
        self.customer.invalidate_wallet_cache()
        self.assertEqual(self.customer.wallet_balance, Decimal('100.00'))
