from decimal import Decimal

from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone

from core.choices import BillingCycle, ServiceStatus, ServiceType
from core.models import Provider, TimeStampedModel


class Service(TimeStampedModel):
    client = models.ForeignKey("clients.Client", on_delete=models.PROTECT, related_name="services", verbose_name="Cliente")
    service_type = models.CharField("Tipo de serviço", max_length=20, choices=ServiceType.choices, db_index=True)
    name = models.CharField("Designação", max_length=180)
    provider = models.ForeignKey(
        Provider, on_delete=models.SET_NULL, null=True, blank=True, related_name="services", verbose_name="Fornecedor"
    )
    description = models.TextField("Descrição", blank=True)
    status = models.CharField("Estado", max_length=25, choices=ServiceStatus.choices, default=ServiceStatus.ACTIVE, db_index=True)
    start_date = models.DateField("Data de início", null=True, blank=True)
    next_renewal_date = models.DateField("Próxima renovação", null=True, blank=True, db_index=True)
    billing_cycle = models.CharField("Periodicidade", max_length=20, choices=BillingCycle.choices, default=BillingCycle.ANNUAL)
    notice_days = models.PositiveSmallIntegerField("Avisar com antecedência (dias)", default=30)
    cost_price = models.DecimalField("Preço de custo", max_digits=10, decimal_places=2, default=Decimal("0.00"))
    sale_price = models.DecimalField("Valor a cobrar", max_digits=10, decimal_places=2, default=Decimal("0.00"))
    tax_rate = models.DecimalField("IVA (%)", max_digits=5, decimal_places=2, default=Decimal("23.00"))
    auto_renew = models.BooleanField("Renovação automática", default=False)
    is_recurring = models.BooleanField("Serviço recorrente", default=True)
    customer_pays_provider_directly = models.BooleanField("Pago diretamente pelo cliente", default=False)
    is_complimentary = models.BooleanField("Oferta", default=False)
    internal_notes = models.TextField("Observações internas", blank=True)

    class Meta:
        verbose_name = "Serviço"
        verbose_name_plural = "Serviços"
        ordering = ["next_renewal_date", "client__name", "name"]
        indexes = [
            models.Index(fields=["status", "next_renewal_date"]),
            models.Index(fields=["client", "service_type"]),
        ]

    def clean(self):
        errors = {}
        if self.is_recurring and self.status == ServiceStatus.ACTIVE and not self.next_renewal_date:
            errors["next_renewal_date"] = "Um serviço recorrente ativo deve ter uma próxima data de renovação."
        if self.is_complimentary and self.sale_price:
            errors["sale_price"] = "Um serviço marcado como oferta deve ter valor a cobrar igual a zero."
        if errors:
            raise ValidationError(errors)

    @property
    def margin(self):
        return self.sale_price - self.cost_price

    @property
    def days_until_renewal(self):
        if not self.next_renewal_date:
            return None
        return (self.next_renewal_date - timezone.localdate()).days

    @property
    def needs_attention(self):
        return self.is_recurring and (
            not self.next_renewal_date or (self.days_until_renewal is not None and self.days_until_renewal <= self.notice_days)
        )

    def __str__(self):
        return f"{self.client} — {self.name}"
