# -*- coding: utf-8 -*-
"""
Тесты для сервиса кошелька (WalletService).

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

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

from customers.models import Customer
from customers.services.wallet_service import WalletService


class WalletServiceTestCase(TenantTestCase):
    """Тесты WalletService."""

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

    def tearDown(self):
        cache.clear()

    def test_create_transaction_deposit(self):
        """create_transaction создаёт пополнение с положительной суммой."""
        txn = WalletService.create_transaction(
            customer=self.customer,
            amount=Decimal('50.00'),
            transaction_type='deposit',
            description='Тестовое пополнение'
        )

        self.assertEqual(txn.signed_amount, Decimal('50.00'))
        self.assertEqual(txn.transaction_type, 'deposit')
        self.assertEqual(txn.balance_after, Decimal('50.00'))
        self.assertEqual(self.customer.wallet_balance, Decimal('50.00'))

    def test_create_transaction_spend(self):
        """create_transaction создаёт списание с отрицательной суммой."""
        # Сначала пополняем
        WalletService.create_transaction(
            customer=self.customer,
            amount=Decimal('100.00'),
            transaction_type='deposit'
        )

        # Затем списываем
        txn = WalletService.create_transaction(
            customer=self.customer,
            amount=Decimal('30.00'),
            transaction_type='spend',
            description='Тестовое списание'
        )

        self.assertEqual(txn.signed_amount, Decimal('-30.00'))
        self.assertEqual(txn.transaction_type, 'spend')
        self.assertEqual(txn.balance_after, Decimal('70.00'))
        self.assertEqual(self.customer.wallet_balance, Decimal('70.00'))

    def test_create_transaction_spend_insufficient_funds(self):
        """Списание при недостаточном балансе вызывает ValueError."""
        with self.assertRaises(ValueError) as context:
            WalletService.create_transaction(
                customer=self.customer,
                amount=Decimal('100.00'),
                transaction_type='spend'
            )

        self.assertIn('Недостаточно средств', str(context.exception))

    def test_adjust_balance_positive(self):
        """Положительная корректировка увеличивает баланс."""
        txn = WalletService.adjust_balance(
            customer_id=self.customer.pk,
            amount=Decimal('75.00'),
            description='Тестовое пополнение администратором',
            user=None
        )

        self.assertEqual(txn.signed_amount, Decimal('75.00'))
        self.assertEqual(txn.transaction_type, 'adjustment')
        self.assertEqual(self.customer.wallet_balance, Decimal('75.00'))

    def test_adjust_balance_negative(self):
        """Отрицательная корректировка уменьшает баланс."""
        # Сначала пополняем
        WalletService.adjust_balance(
            customer_id=self.customer.pk,
            amount=Decimal('100.00'),
            description='Начальное пополнение',
            user=None
        )

        # Отрицательная корректировка
        txn = WalletService.adjust_balance(
            customer_id=self.customer.pk,
            amount=Decimal('-40.00'),
            description='Списание администратором',
            user=None
        )

        self.assertEqual(txn.signed_amount, Decimal('-40.00'))
        self.assertEqual(self.customer.wallet_balance, Decimal('60.00'))

    def test_adjust_balance_negative_insufficient(self):
        """Отрицательная корректировка с недостаточным балансом вызывает ValueError."""
        with self.assertRaises(ValueError) as context:
            WalletService.adjust_balance(
                customer_id=self.customer.pk,
                amount=Decimal('-50.00'),
                description='Списание',
                user=None
            )

        self.assertIn('отрицательному балансу', str(context.exception))

    def test_adjust_balance_requires_description(self):
        """Корректировка без описания вызывает ValueError."""
        with self.assertRaises(ValueError) as context:
            WalletService.adjust_balance(
                customer_id=self.customer.pk,
                amount=Decimal('50.00'),
                description='',
                user=None
            )

        self.assertIn('Описание обязательно', str(context.exception))

    def test_adjust_balance_zero_amount_fails(self):
        """Корректировка с нулевой суммой вызывает ValueError."""
        with self.assertRaises(ValueError) as context:
            WalletService.adjust_balance(
                customer_id=self.customer.pk,
                amount=Decimal('0'),
                description='Нулевая корректировка',
                user=None
            )

        self.assertIn('не может быть нулевой', str(context.exception))
