import datetime
from pathlib import Path
from uuid import uuid4

from account.models import AccountModel
from django.core.validators import FileExtensionValidator
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from main.models import NummiQuerySet
from main.utils import pdf_outline_to_str
from media.utils import get_path
from pypdf import PdfReader


class StatementQuerySet(NummiQuerySet):
    main_field = "metadata"
    fields = {
        "tags": "B",
    }


class Statement(AccountModel):
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    date = models.DateField(default=datetime.date.today, verbose_name=_("End date"))
    start_date = models.DateField(
        default=datetime.date.today, verbose_name=_("Start date")
    )
    value = models.DecimalField(
        max_digits=12, decimal_places=2, default=0, verbose_name=_("End value")
    )
    start_value = models.DecimalField(
        max_digits=12, decimal_places=2, default=0, verbose_name=_("Start value")
    )
    file = models.FileField(
        upload_to=get_path,
        validators=[FileExtensionValidator(["pdf"])],
        verbose_name=_("File"),
        max_length=256,
        blank=True,
        default="",
    )
    metadata = models.TextField(blank=True)
    tags = models.TextField(blank=True)

    objects = StatementQuerySet.as_manager()

    def __str__(self):
        return _("%(date)s statement") % {"date": self.date}

    def save(self, *args, **kwargs):
        if Statement.objects.filter(id=self.id).exists():
            _prever = Statement.objects.get(id=self.id)
            if _prever.file and _prever.file != self.file:
                Path(_prever.file.path).unlink(missing_ok=True)

        if self.file:
            reader = PdfReader(self.file)

            if reader.metadata:
                self.metadata = " ".join(
                    (
                        m.replace("\x00", "").strip()
                        for m in (
                            reader.metadata.title,
                            reader.metadata.author,
                            reader.metadata.subject,
                        )
                        if m
                    )
                )

            _tags = pdf_outline_to_str(reader.outline)
            _tags += " ".join(
                (page.extract_text().replace("\x00", "") for page in reader.pages)
            )
            self.tags = " ".join((tag for tag in _tags.split() if len(tag) >= 3))

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

    @property
    def sum(self):
        return self.transaction_set.aggregate(sum=models.Sum("value", default=0)).get(
            "sum"
        )

    @property
    def diff(self):
        return self.value - self.start_value

    def delete(self, *args, **kwargs):
        if self.file:
            self.file.delete()
        super().delete(*args, **kwargs)

    def get_absolute_url(self):
        return reverse("statement", args=(self.pk,))

    def get_delete_url(self):
        return reverse("del_statement", args=(self.pk,))

    class Meta:
        ordering = ["-date", "account"]
        verbose_name = _("Statement")
        verbose_name_plural = _("Statements")
