import random
from django.db import models
from django.utils import timezone
from apps.accounts.models import User
from apps.business.wallet.models import Wallet
from apps.core.models import BaseModel


class WithdrawalDeductionConfig(BaseModel):
    name = models.CharField(max_length=100, default='Default')
    # Named deduction components (percentages)
    tds_percent = models.DecimalField(max_digits=6, decimal_places=3, default=5, verbose_name='TDS (%)')
    repurchase_percent = models.DecimalField(max_digits=6, decimal_places=3, default=5, verbose_name='To Repurchase Wallet (%)')
    welfare_fund_percent = models.DecimalField(max_digits=6, decimal_places=3, default=5, verbose_name='Welfare Fund (%)')
    technology_charges_percent = models.DecimalField(max_digits=6, decimal_places=3, default=5, verbose_name='Technology Charges (%)')
    operations_charges_percent = models.DecimalField(max_digits=6, decimal_places=3, default=5, verbose_name='Operations/Admin Charges (%)')
    # Legacy fields kept for database compatibility (not used in new calculations)
    admin_fee_percent = models.DecimalField(max_digits=6, decimal_places=3, default=0)
    processing_fee_fixed = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    is_active = models.BooleanField(default=True, db_index=True)

    @property
    def total_deduction_percent(self):
        from decimal import Decimal
        return (
            Decimal(self.tds_percent)
            + Decimal(self.repurchase_percent)
            + Decimal(self.welfare_fund_percent)
            + Decimal(self.technology_charges_percent)
            + Decimal(self.operations_charges_percent)
        )

    class Meta:
        ordering = ['-is_active', '-updated_at']

    def __str__(self):
        return f"{self.name} ({'active' if self.is_active else 'inactive'})"

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self.is_active:
            WithdrawalDeductionConfig.objects.filter(is_active=True).exclude(pk=self.pk).update(is_active=False)


class BankAccount(BaseModel):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bank_accounts')
    account_holder_name = models.CharField(max_length=200)
    account_number = models.CharField(max_length=30)
    ifsc_code = models.CharField(max_length=20)
    bank_name = models.CharField(max_length=200)
    is_verified = models.BooleanField(default=False)
    is_primary = models.BooleanField(default=False)

    class Meta:
        ordering = ['-is_primary', '-created_at']

    def __str__(self):
        return f"{self.bank_name} ****{self.account_number[-4:]} ({self.user})"

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self.is_primary:
            BankAccount.objects.filter(user=self.user, is_primary=True).exclude(pk=self.pk).update(is_primary=False)

    @property
    def masked_account_number(self):
        num = self.account_number
        if len(num) <= 4:
            return num
        return '****' + num[-4:]


class BankAccountOTP(models.Model):
    bank_account = models.ForeignKey(BankAccount, on_delete=models.CASCADE, related_name='otps')
    otp_code = models.CharField(max_length=10)
    expires_at = models.DateTimeField()
    is_used = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    @staticmethod
    def generate_code():
        return str(random.randint(100000, 999999))

    def is_valid(self):
        return not self.is_used and self.expires_at > timezone.now()


class WithdrawalRequest(models.Model):
    class Status(models.TextChoices):
        PENDING = 'PENDING', 'Pending'
        APPROVED = 'APPROVED', 'Approved'
        REJECTED = 'REJECTED', 'Rejected'
        PAID = 'PAID', 'Paid'

    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='withdrawal_requests')
    bank_account = models.ForeignKey(BankAccount, null=True, blank=True, on_delete=models.SET_NULL, related_name='withdrawals')
    amount_requested = models.DecimalField(max_digits=12, decimal_places=2)
    tds_amount = models.DecimalField(max_digits=12, decimal_places=2)
    admin_fee_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    processing_fee_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    total_deduction_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    net_amount = models.DecimalField(max_digits=12, decimal_places=2)
    upstream_gross_amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    source = models.CharField(max_length=64, blank=True, default='')
    deduction_config = models.ForeignKey(WithdrawalDeductionConfig, null=True, blank=True, on_delete=models.SET_NULL, related_name='withdrawals')
    status = models.CharField(max_length=10, choices=Status.choices, default=Status.PENDING)
    reference_id = models.CharField(max_length=32, blank=True, null=True, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)
    processed_at = models.DateTimeField(null=True, blank=True)
    remarks = models.TextField(blank=True, null=True)

    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user']),
            models.Index(fields=['status']),
            models.Index(fields=['created_at']),
        ]

    def __str__(self):
        return f"WithdrawalRequest({self.user_id}, {self.amount_requested}, {self.status})"

# Wallet locking
from apps.business.wallet.models import Wallet
if not hasattr(Wallet, 'locked_amount'):
    Wallet.add_to_class('locked_amount', models.DecimalField(max_digits=12, decimal_places=2, default=0))
