from django.db import models
from accounts.models import CustomUser
from decimal import Decimal
from django.db import transaction
from django.core.exceptions import ValidationError


class Transaction(models.Model):
    """
    Финансовая транзакция по заказу.
    Хранит историю всех платежей и возвратов.
    
    Транзакция может быть:
    - payment: клиент платит (увеличивает amount_paid)
    - refund: возврат клиенту (уменьшает amount_paid)
    
    Поддерживает:
    - Смешанную оплату (несколько транзакций разными способами)
    - Частичные возвраты (любая сумма)
    - Полную историю движения денег
    """
    
    TRANSACTION_TYPE_CHOICES = [
        ('payment', 'Платёж'),
        ('refund', 'Возврат'),
    ]
    
    order = models.ForeignKey(
        'Order',
        on_delete=models.CASCADE,
        related_name='transactions',
        verbose_name="Заказ"
    )
    
    transaction_type = models.CharField(
        max_length=20,
        choices=TRANSACTION_TYPE_CHOICES,
        default='payment',
        verbose_name="Тип транзакции"
    )
    
    amount = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        verbose_name="Сумма",
        help_text="Всегда положительная. Для возврата используется transaction_type='refund'"
    )
    
    payment_method = models.ForeignKey(
        'PaymentMethod',
        on_delete=models.PROTECT,
        related_name='transactions',
        verbose_name="Способ оплаты/возврата"
    )
    
    # Для возвратов - опциональная связь с исходным платежом
    related_payment = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='refunds',
        verbose_name="Связанный платёж",
        help_text="Для возвратов - на какой платёж ссылается этот возврат"
    )
    
    transaction_date = models.DateTimeField(
        auto_now_add=True,
        verbose_name="Дата и время транзакции"
    )
    
    created_by = models.ForeignKey(
        CustomUser,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='transactions_created',
        verbose_name="Создал"
    )
    
    notes = models.TextField(
        blank=True,
        null=True,
        verbose_name="Примечания"
    )
    
    reason = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Причина",
        help_text="Причина возврата или особенности платежа"
    )
    
    class Meta:
        verbose_name = "Транзакция"
        verbose_name_plural = "Транзакции"
        ordering = ['-transaction_date']
        indexes = [
            models.Index(fields=['order', '-transaction_date']),
            models.Index(fields=['transaction_type']),
            models.Index(fields=['payment_method']),
            models.Index(fields=['transaction_date']),
        ]
    
    def __str__(self):
        type_name = self.get_transaction_type_display()
        return f"{type_name} {self.amount} руб. по заказу #{self.order.order_number}"
    
    def clean(self):
        """Валидация транзакции"""
        super().clean()
        
        # Сумма всегда положительная
        if self.amount <= 0:
            raise ValidationError({'amount': 'Сумма должна быть положительной'})
        
        # Для возврата related_payment должен быть payment
        if self.transaction_type == 'refund' and self.related_payment:
            if self.related_payment.transaction_type != 'payment':
                raise ValidationError({
                    'related_payment': 'Связанная транзакция должна быть платежом'
                })
    
    def save(self, *args, **kwargs):
        """При сохранении обновляем баланс заказа и обрабатываем кошелёк"""
        is_new = self.pk is None

        with transaction.atomic():
            super().save(*args, **kwargs)

            # Пересчитываем баланс заказа
            self.order.recalculate_amount_paid()

            # Обработка кошелька только для новых транзакций
            if is_new and self.payment_method.code == 'account_balance':
                from customers.services.wallet_service import WalletService

                if self.transaction_type == 'payment':
                    # Списание из кошелька
                    WalletService.create_wallet_spend(
                        order=self.order,
                        amount=self.amount,
                        user=self.created_by
                    )

                elif self.transaction_type == 'refund':
                    # Возврат в кошелёк
                    WalletService.create_wallet_deposit(
                        order=self.order,
                        amount=self.amount,
                        user=self.created_by
                    )
