"""
CODH Payments Models
Payment processing and invoicing
"""

import uuid
from decimal import Decimal
from django.db import models
from django.conf import settings
from django.utils import timezone


class Invoice(models.Model):
    """
    Invoices for services
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='invoices')
    
    # Invoice Details
    invoice_number = models.CharField(max_length=50, unique=True)
    
    # Related objects
    subscription = models.ForeignKey('subscriptions.Subscription', on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices')
    project = models.ForeignKey('projects.Project', on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices')
    
    # Line items
    items = models.JSONField(default=list)  # [{description, quantity, unit_price, total}]
    
    # Amounts
    subtotal = models.DecimalField(max_digits=12, decimal_places=2)
    tax_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
    tax_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    discount_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    total = models.DecimalField(max_digits=12, decimal_places=2)
    
    currency = models.CharField(max_length=3, default='USD')
    
    # Status
    STATUS_CHOICES = [
        ('draft', 'Draft'),
        ('sent', 'Sent'),
        ('paid', 'Paid'),
        ('overdue', 'Overdue'),
        ('cancelled', 'Cancelled'),
        ('refunded', 'Refunded'),
    ]
    status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='draft')
    
    # Dates
    issue_date = models.DateField()
    due_date = models.DateField()
    paid_date = models.DateField(null=True, blank=True)
    
    # Notes
    notes = models.TextField(blank=True)
    terms = models.TextField(blank=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Invoice'
        verbose_name_plural = 'Invoices'
        ordering = ['-created_at']
    
    def __str__(self):
        return self.invoice_number
    
    def calculate_totals(self):
        """Calculate invoice totals"""
        self.subtotal = sum(item['total'] for item in self.items)
        self.tax_amount = self.subtotal * (self.tax_rate / 100)
        self.total = self.subtotal + self.tax_amount - self.discount_amount
        self.save()


class Payment(models.Model):
    """
    Payment records
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='payments')
    invoice = models.ForeignKey(Invoice, on_delete=models.SET_NULL, null=True, blank=True, related_name='payments')
    
    # Payment Details
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    currency = models.CharField(max_length=3, default='USD')
    
    # Gateway
    GATEWAY_CHOICES = [
        ('paystack', 'Paystack'),
        ('flutterwave', 'Flutterwave'),
        ('stripe', 'Stripe'),
        ('bank_transfer', 'Bank Transfer'),
        ('cash', 'Cash'),
        ('wallet', 'Wallet'),
    ]
    gateway = models.CharField(max_length=20, choices=GATEWAY_CHOICES)
    
    # Transaction IDs
    transaction_id = models.CharField(max_length=255, blank=True)
    gateway_reference = models.CharField(max_length=255, blank=True)
    
    # Status
    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('processing', 'Processing'),
        ('completed', 'Completed'),
        ('failed', 'Failed'),
        ('refunded', 'Refunded'),
        ('disputed', 'Disputed'),
    ]
    status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='pending')
    
    # Metadata
    metadata = models.JSONField(default=dict, blank=True)
    
    # Failure reason
    failure_reason = models.TextField(blank=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Payment'
        verbose_name_plural = 'Payments'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.gateway} - {self.amount} {self.currency}"
    
    @classmethod
    def get_today_revenue(cls):
        """Get today's revenue"""
        today = timezone.now().date()
        payments = cls.objects.filter(
            status='completed',
            created_at__date=today
        )
        return sum(p.amount for p in payments)
    
    @classmethod
    def get_month_revenue(cls):
        """Get this month's revenue"""
        now = timezone.now()
        payments = cls.objects.filter(
            status='completed',
            created_at__year=now.year,
            created_at__month=now.month
        )
        return sum(p.amount for p in payments)
    
    @classmethod
    def get_year_revenue(cls):
        """Get this year's revenue"""
        now = timezone.now()
        payments = cls.objects.filter(
            status='completed',
            created_at__year=now.year
        )
        return sum(p.amount for p in payments)


class Wallet(models.Model):
    """
    User wallet for credits/balance
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='wallet')
    
    balance = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    currency = models.CharField(max_length=3, default='USD')
    
    is_active = models.BooleanField(default=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Wallet'
        verbose_name_plural = 'Wallets'
    
    def credit(self, amount, description='', reference=''):
        """Add credit to wallet"""
        self.balance += Decimal(str(amount))
        self.save()
        
        WalletTransaction.objects.create(
            wallet=self,
            type='credit',
            amount=amount,
            description=description,
            reference=reference,
            balance_after=self.balance
        )
    
    def debit(self, amount, description='', reference=''):
        """Deduct from wallet"""
        if self.balance < Decimal(str(amount)):
            raise ValueError("Insufficient balance")
        
        self.balance -= Decimal(str(amount))
        self.save()
        
        WalletTransaction.objects.create(
            wallet=self,
            type='debit',
            amount=amount,
            description=description,
            reference=reference,
            balance_after=self.balance
        )


class WalletTransaction(models.Model):
    """
    Wallet transaction history
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
    wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE, related_name='transactions')
    
    TYPE_CHOICES = [
        ('credit', 'Credit'),
        ('debit', 'Debit'),
    ]
    type = models.CharField(max_length=10, choices=TYPE_CHOICES)
    
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    description = models.CharField(max_length=255, blank=True)
    reference = models.CharField(max_length=255, blank=True)
    
    balance_after = models.DecimalField(max_digits=12, decimal_places=2)
    
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        verbose_name = 'Wallet Transaction'
        verbose_name_plural = 'Wallet Transactions'
        ordering = ['-created_at']


class RevenueLog(models.Model):
    """
    Daily revenue tracking for analytics
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    
    date = models.DateField(unique=True)
    
    # Revenue breakdown
    hosting_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    subscription_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    development_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    maintenance_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    other_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    
    # Totals
    gross_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    refunds = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    net_revenue = models.DecimalField(max_digits=12, decimal_places=2, default=0)
    
    # Metrics
    successful_payments = models.IntegerField(default=0)
    failed_payments = models.IntegerField(default=0)
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Revenue Log'
        verbose_name_plural = 'Revenue Logs'
        ordering = ['-date']
    
    def calculate_net(self):
        """Calculate net revenue"""
        self.gross_revenue = (
            self.hosting_revenue +
            self.subscription_revenue +
            self.development_revenue +
            self.maintenance_revenue +
            self.other_revenue
        )
        self.net_revenue = self.gross_revenue - self.refunds
        self.save()
