from django.conf import settings
from django.db import models

from apps.common.models import TimeStampedModel


class Payout(TimeStampedModel):
    """
    A withdrawal of wallet balance to mobile money / bank.

    Money is reserved from the wallet into the clearing account when the payout
    is requested (status=pending), settled to cash on provider success, or
    reversed back to the wallet on failure/rejection. `idempotency_key` makes
    requests safe to retry; the linked ledger transactions are keyed too so the
    money side can never double-post.
    """

    class Method(models.TextChoices):
        MOBILE_MONEY = 'mobile_money', 'Mobile money'
        BANK_ACCOUNT = 'bank_account', 'Bank account'

    class Status(models.TextChoices):
        PENDING = 'pending', 'Pending'
        PROCESSING = 'processing', 'Processing'
        PAID = 'paid', 'Paid'
        REJECTED = 'rejected', 'Rejected'
        FAILED = 'failed', 'Failed'

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name='payouts')
    amount = models.DecimalField(max_digits=14, decimal_places=2)
    payout_method = models.CharField(max_length=16, choices=Method.choices)
    provider = models.CharField(max_length=40)          # mpesa | tigo | airtel | bank name
    account_name = models.CharField(max_length=120)
    account_number = models.CharField(max_length=40, blank=True)  # msisdn / bank account

    status = models.CharField(
        max_length=12, choices=Status.choices, default=Status.PENDING, db_index=True)
    idempotency_key = models.CharField(max_length=120, unique=True)
    provider_reference = models.CharField(max_length=120, blank=True)
    failure_reason = models.CharField(max_length=255, blank=True)

    reserve_txn = models.ForeignKey(
        'ledger.Transaction', null=True, blank=True,
        on_delete=models.SET_NULL, related_name='+')
    settle_txn = models.ForeignKey(
        'ledger.Transaction', null=True, blank=True,
        on_delete=models.SET_NULL, related_name='+')

    paid_at = models.DateTimeField(null=True, blank=True)
    processed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True,
        on_delete=models.SET_NULL, related_name='processed_payouts')

    class Meta:
        db_table = 'payouts'
        ordering = ['-created_at']
        indexes = [models.Index(fields=['user', 'status'])]

    def __str__(self):
        return f'Payout #{self.pk} · {self.amount} → {self.user_id} [{self.status}]'

    @property
    def is_terminal(self) -> bool:
        return self.status in (self.Status.PAID, self.Status.REJECTED, self.Status.FAILED)
