import uuid

from django.db import models

from apps.accounts.models import Company, TimeStampedModel, User
from apps.customers.models import Customer
from apps.templates.models import InvoiceTemplate


class Invoice(TimeStampedModel):
    class Status(models.TextChoices):
        DRAFT = 'draft', 'Draft'
        SENT = 'sent', 'Sent'
        VIEWED = 'viewed', 'Viewed'
        PAID = 'paid', 'Paid'
        PARTIALLY_PAID = 'partially_paid', 'Partially Paid'
        OVERDUE = 'overdue', 'Overdue'
        CANCELLED = 'cancelled', 'Cancelled'

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='invoices')
    customer = models.ForeignKey(Customer, on_delete=models.PROTECT, related_name='invoices')
    template = models.ForeignKey(
        InvoiceTemplate, on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices'
    )
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, related_name='invoices_created'
    )
    invoice_number = models.CharField(max_length=64, unique=True)
    status = models.CharField(max_length=32, choices=Status.choices, default=Status.DRAFT)
    issue_date = models.DateField()
    due_date = models.DateField()
    currency = models.CharField(max_length=10, default='KES')
    subtotal = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    tax_amount = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    discount_amount = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    total = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    amount_paid = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    bank_details = models.TextField(blank=True)
    payment_instructions = models.TextField(blank=True)
    terms_and_conditions = models.TextField(blank=True)
    notes = models.TextField(blank=True)
    is_archived = models.BooleanField(default=False)
    # Per-invoice override of who the invoice is *from*. Blank means "use the
    # company's own profile" — not every invoice a company sends is
    # necessarily from that company (e.g. a side business, a different
    # branch identity), so these let a single invoice present as sent by
    # someone else without touching the company's actual profile.
    sender_name = models.CharField(max_length=255, blank=True)
    sender_address = models.TextField(blank=True)
    sender_email = models.EmailField(blank=True)
    sender_phone = models.CharField(max_length=50, blank=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return self.invoice_number

    @property
    def balance_due(self):
        return self.total - self.amount_paid


class InvoiceItem(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='items')
    description = models.CharField(max_length=500)
    quantity = models.DecimalField(max_digits=12, decimal_places=2, default=1)
    unit = models.CharField(max_length=50, blank=True)
    unit_price = models.DecimalField(max_digits=14, decimal_places=2, default=0)
    tax_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
    discount_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0)
    order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['order']

    def __str__(self):
        return f'{self.invoice.invoice_number} - {self.description}'

    @property
    def line_total(self):
        base = self.quantity * self.unit_price
        after_discount = base - (base * self.discount_rate / 100)
        return after_discount + (after_discount * self.tax_rate / 100)
