import uuid

from django.core.exceptions import ValidationError
from django.db import models
from simple_history.models import HistoricalRecords


class TimeStampedModel(models.Model):
    public_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    created_at = models.DateTimeField("Criado em", auto_now_add=True)
    updated_at = models.DateTimeField("Atualizado em", auto_now=True)
    history = HistoricalRecords(inherit=True)

    class Meta:
        abstract = True


class Provider(TimeStampedModel):
    class ProviderType(models.TextChoices):
        REGISTRAR = "registrar", "Registador de domínios"
        HOSTING = "hosting", "Fornecedor de alojamento"
        SERVER = "server", "Servidor / cloud"
        PAYMENT = "payment", "Pagamentos"
        OTHER = "other", "Outro"

    name = models.CharField("Nome", max_length=150, unique=True)
    provider_type = models.CharField("Tipo", max_length=20, choices=ProviderType.choices, default=ProviderType.OTHER)
    website = models.URLField("Website", blank=True)
    support_email = models.EmailField("Email de suporte", blank=True)
    support_phone = models.CharField("Telefone", max_length=40, blank=True)
    account_reference = models.CharField(
        "Referência da conta",
        max_length=150,
        blank=True,
        help_text="Identificador ou referência; nunca guardar a password.",
    )
    notes = models.TextField("Notas", blank=True)
    is_active = models.BooleanField("Ativo", default=True)

    class Meta:
        verbose_name = "Fornecedor"
        verbose_name_plural = "Fornecedores"
        ordering = ["name"]

    def __str__(self):
        return self.name


class PortalConfiguration(TimeStampedModel):
    company_name = models.CharField("Nome da empresa", max_length=180, default="Kreate4Web")
    company_email = models.EmailField("Email", blank=True)
    company_phone = models.CharField("Telefone", max_length=40, blank=True)
    portal_base_url = models.URLField("URL pública do portal", blank=True, help_text="Exemplo: https://portal.kreate4web.com")
    company_nif = models.CharField("NIF", max_length=20, blank=True)
    mbway_phone = models.CharField("Número MB WAY", max_length=40, blank=True)
    iban = models.CharField("IBAN", max_length=40, blank=True)
    default_notice_days = models.PositiveSmallIntegerField("Primeiro aviso (dias)", default=30)
    second_notice_days = models.PositiveSmallIntegerField("Segundo aviso (dias)", default=15)
    final_notice_days = models.PositiveSmallIntegerField("Aviso final (dias)", default=7)
    internal_notification_email = models.EmailField("Email para alertas internos", blank=True)
    reply_to_email = models.EmailField("Email de resposta", blank=True)
    email_test_mode = models.BooleanField(
        "Modo de teste de email",
        default=True,
        help_text="Redireciona todas as mensagens para o destinatário de testes, preservando o destinatário original no histórico.",
    )
    email_test_recipient = models.EmailField("Destinatário de testes", blank=True)
    auto_prepare_notifications = models.BooleanField("Preparar notificações automaticamente", default=True)
    auto_send_notifications = models.BooleanField(
        "Enviar notificações automaticamente",
        default=False,
        help_text="Ative apenas depois de validar o SMTP e os modelos em modo de teste.",
    )
    notification_max_attempts = models.PositiveSmallIntegerField("Máximo de tentativas", default=3)
    notification_retry_minutes = models.PositiveSmallIntegerField("Intervalo base de repetição (minutos)", default=30)
    notes = models.TextField("Notas", blank=True)

    class Meta:
        verbose_name = "Configuração do portal"
        verbose_name_plural = "Configuração do portal"

    def clean(self):
        if not self.pk and PortalConfiguration.objects.exists():
            raise ValidationError("Só pode existir uma configuração global do portal.")

    def __str__(self):
        return self.company_name


class Document(TimeStampedModel):
    class Category(models.TextChoices):
        CONTRACT = "contract", "Contrato"
        INVOICE = "invoice", "Fatura"
        RECEIPT = "receipt", "Recibo"
        PAYMENT_PROOF = "payment_proof", "Comprovativo"
        DOMAIN = "domain", "Documento de domínio"
        TECHNICAL = "technical", "Documento técnico"
        REPORT = "report", "Relatório"
        OTHER = "other", "Outro"

    title = models.CharField("Título", max_length=220)
    category = models.CharField("Categoria", max_length=25, choices=Category.choices, default=Category.OTHER, db_index=True)
    client = models.ForeignKey(
        "clients.Client",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="documents",
        verbose_name="Cliente",
    )
    service = models.ForeignKey(
        "services.Service",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="documents",
        verbose_name="Serviço",
    )
    payment = models.ForeignKey(
        "billing.Payment",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="documents",
        verbose_name="Pagamento",
    )
    support_ticket = models.ForeignKey(
        "support.SupportTicket",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="documents",
        verbose_name="Pedido de suporte",
    )
    file = models.FileField("Ficheiro", upload_to="documents/%Y/%m/", blank=True)
    issued_on = models.DateField("Data do documento", null=True, blank=True)
    expires_on = models.DateField("Válido até", null=True, blank=True, db_index=True)
    reference = models.CharField("Referência", max_length=150, blank=True)
    visible_to_client = models.BooleanField("Visível no portal do cliente", default=False)
    uploaded_by = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="uploaded_portal_documents",
        verbose_name="Carregado por",
    )
    notes = models.TextField("Notas", blank=True)

    class Meta:
        verbose_name = "Documento"
        verbose_name_plural = "Documentos"
        ordering = ["-issued_on", "-created_at"]
        indexes = [models.Index(fields=["category", "expires_on"])]

    def clean(self):
        if not any((self.client_id, self.service_id, self.payment_id, self.support_ticket_id)):
            raise ValidationError("Associe o documento a um cliente, serviço, pagamento ou pedido de suporte.")
        if self.issued_on and self.expires_on and self.expires_on < self.issued_on:
            raise ValidationError({"expires_on": "A validade não pode ser anterior à data do documento."})

    def __str__(self):
        return self.title
