from django.db import models
from django.utils import timezone
from decimal import Decimal
from customers.models import Customer, Service
from datetime import datetime, timedelta
import uuid

class Invoice(models.Model):
    STATUS_CHOICES = [
        ('unpaid', 'Unpaid'),
        ('paid', 'Paid'),
        ('overdue', 'Overdue'),
        ('cancelled', 'Cancelled'),
    ]

    invoice_number = models.CharField(max_length=20, unique=True)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='invoices')
    service = models.ForeignKey(Service, on_delete=models.SET_NULL, null=True)

    # Amounts
    service_amount = models.DecimalField(max_digits=10, decimal_places=2)

    # Keep package_amount as an alias for backward compatibility
    @property
    def package_amount(self):
        return self.service_amount

    @property
    def package(self):
        return self.service
    installation_fee = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00'))
    penalty_amount = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00'))
    total_amount = models.DecimalField(max_digits=10, decimal_places=2)

    # Dates
    issue_date = models.DateField(default=timezone.now)
    due_date = models.DateField()
    billing_period_start = models.DateField()
    billing_period_end = models.DateField()

    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='unpaid')
    notes = models.TextField(blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"Invoice {self.invoice_number} - {self.customer.full_name}"

    def save(self, *args, **kwargs):
        if not self.invoice_number:
            self.invoice_number = f"INV-{timezone.now().strftime('%Y%m%d')}-{str(uuid.uuid4())[:8].upper()}"

        # Calculate total amount
        self.total_amount = self.service_amount + self.installation_fee + self.penalty_amount

        super().save(*args, **kwargs)

    @property
    def is_overdue(self):
        return self.status == 'unpaid' and self.due_date < timezone.now().date()

class ServicePeriod(models.Model):
    STATUS_CHOICES = [
        ('active', 'Active'),
        ('expired', 'Expired'),
        ('suspended', 'Suspended'),
        ('cancelled', 'Cancelled'),
    ]

    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='service_periods')
    service = models.ForeignKey(Service, on_delete=models.CASCADE)
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, null=True, blank=True)

    # Keep package as an alias for backward compatibility
    @property
    def package(self):
        return self.service

    # Service period timing (with exact time precision)
    service_start = models.DateTimeField(help_text="Exact start time of service period")
    service_end = models.DateTimeField(help_text="Exact end time of service period")

    # Status and tracking
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
    is_auto_renewed = models.BooleanField(default=False, help_text="Was this period auto-renewed from account balance?")
    renewal_attempted_at = models.DateTimeField(null=True, blank=True)
    suspended_at = models.DateTimeField(null=True, blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.customer.customer_id} - {self.service_start.strftime('%Y-%m-%d %H:%M')} to {self.service_end.strftime('%Y-%m-%d %H:%M')}"

    @property
    def is_active(self):
        now = timezone.now()
        return self.status == 'active' and self.service_start <= now <= self.service_end

    @property
    def is_expired(self):
        return timezone.now() > self.service_end or self.status == 'expired'

    @property
    def time_remaining(self):
        if self.is_expired:
            return timedelta(0)
        return self.service_end - timezone.now()

    @property
    def days_remaining(self):
        return self.time_remaining.days

    def calculate_next_period_dates(self):
        """Calculate the next service period start and end dates"""
        if self.service.billing_cycle == 'monthly':
            next_start = self.service_end
            # Add exactly 30 days for monthly billing
            next_end = next_start + timedelta(days=30)
        elif self.service.billing_cycle == 'quarterly':
            next_start = self.service_end
            next_end = next_start + timedelta(days=90)
        else:  # annually
            next_start = self.service_end
            next_end = next_start + timedelta(days=365)

        return next_start, next_end

    class Meta:
        ordering = ['-service_start']

class BillingCycle(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    next_billing_date = models.DateField()
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.customer.full_name} - Next: {self.next_billing_date}"