import decimal
import typing

from django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

if typing.TYPE_CHECKING:
    from accounts.models import User

from subjects import models as subject_models

UserModel: 'User' = get_user_model()


class Invoice(models.Model):
    class Meta:
        verbose_name = _('Invoice')
        verbose_name_plural = _('Invoices')

    user = models.ForeignKey(UserModel, models.CASCADE)
    supplier = models.ForeignKey(
        subject_models.Subject, on_delete=models.CASCADE, related_name='+', verbose_name=_('Supplier'),
    )
    supplier_data = models.ForeignKey(
        subject_models.SubjectData, on_delete=models.CASCADE, related_name='+', verbose_name=_('Supplier data'),
    )

    customer = models.ForeignKey(
        subject_models.Subject, on_delete=models.CASCADE, related_name='+', verbose_name=_('Customer'),
    )
    customer_data = models.ForeignKey(
        subject_models.SubjectData, on_delete=models.CASCADE, related_name='+', verbose_name=_('Customer data'),
    )
    invoice_date = models.DateField(_('Invoice date'), default=timezone.now)
    due_date = models.DateField(_('Due date'))

    def __str__(self):
        return f'{self.id} - {self.supplier_data.name} -> {self.customer_data.name}'

    def total_price(self) -> decimal.Decimal:
        total = decimal.Decimal(0)
        for item in self.items.all():
            total += item.total_price()
        return total

    def custom_id(self) -> str:
        return f"{self.invoice_date.year}-{self.id:04}"


class InvoiceItem(models.Model):
    class Meta:
        verbose_name = _('Invoice Item')
        verbose_name_plural = _('Invoice Items')

    invoice = models.ForeignKey(
        Invoice, on_delete=models.CASCADE, related_name='items',
    )
    amount = models.DecimalField(_('Amount'), decimal_places=3, max_digits=8)
    amount_unit = models.CharField(_('Amount unit'), max_length=32)
    description = models.CharField(_('Description'), max_length=64)
    price_for_amount = models.DecimalField(
        _('Price for amount'), decimal_places=3, max_digits=8,
    )

    def total_price(self) -> decimal.Decimal:
        return self.amount * self.price_for_amount

    def __str__(self):
        return f'{self.id} -> {self.invoice.id}'