import datetime

from django.contrib.gis.db import models
from django.urls import reverse
from django.apps import apps
from django.utils import timezone
from django.utils.html import format_html

from utils.util import render_images, markdown_to_html


def get_upload_path(self, filename):
    return "images/post-images/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename)


class GTDOutcome(models.Model):
    title = models.CharField(max_length=300)
    body_markdown = models.TextField()
    body_html = models.TextField(blank=True)
    date_goal = models.DateField(blank=True, null=True)
    date_ended = models.DateField(blank=True, null=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ('-date_goal',)

    def get_absolute_url(self):
        return reverse('gtd:outcome-detail', kwargs={"pk": self.pk})

    def save(self, *args, **kwargs):
        created = self.pk is None
        if not created:
            md = render_images(self.body_markdown)
            self.body_html = markdown_to_html(md)
        super(GTDOutcome, self).save(*args, **kwargs)


class GTDProject(models.Model):
    LBH = 1
    LXF = 2
    PERSONAL = 3
    BUS = 4
    PROJECT_TYPE = (
        (LBH, 'lbh'),
        (LXF, 'lxf'),
        (PERSONAL, 'personal'),
        (BUS, 'bus'),
    )
    title = models.CharField(max_length=200)
    short_title = models.CharField(max_length=200, blank=True, null=True)
    body_markdown = models.TextField(null=True, blank=True)
    body_html = models.TextField(blank=True)
    date_goal = models.DateField(blank=True, null=True)
    date_ended = models.DateField(blank=True, null=True)
    project_type = models.IntegerField(choices=PROJECT_TYPE, default=PERSONAL)
    outcome = models.ForeignKey(GTDOutcome, on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        ordering = ('-date_goal',)
        get_latest_by = 'date_goal'

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('gtd:project-detail', kwargs={"pk": self.id})

    @property
    def get_previous_admin_url(self):
        n = self.get_previous_by_date_goal()
        return reverse('admin:%s_%s_change' % (self._meta.app_label,  self._meta.model_name),  args=[n.id])

    @property
    def get_next_admin_url(self):
        model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
        try:
            return reverse('admin:%s_%s_change' % (self._meta.app_label,  self._meta.model_name),  args=[self.get_next_by_date_goal().pk])
        except model.DoesNotExist:
            return ''

    def save(self, *args, **kwargs):
        created = self.pk is None
        if not created:
            md = render_images(self.body_markdown)
            self.body_html = markdown_to_html(md)
        super(GTDProject, self).save(*args, **kwargs)


class GTDNote(models.Model):
    title = models.CharField(max_length=200)
    url = models.CharField(max_length=400, blank=True, null=True)
    body_markdown = models.TextField(null=True, blank=True)
    body_html = models.TextField(blank=True)
    date_completed = models.DateField(null=True, blank=True)
    date_created = models.DateTimeField(auto_now=True)
    ACTION = 0
    REMINDER = 1
    REFERENCE = 2
    SOMEDAY = 3
    NOTE_TYPE = [
        (ACTION, 'Action'),
        (REMINDER, 'Reminder'),
        (REFERENCE, 'Reference'),
        (SOMEDAY, 'Someday'),
    ]
    note_type = models.SmallIntegerField(choices=NOTE_TYPE, default=ACTION)
    reminder = models.BigIntegerField(help_text="In days", null=True, blank=True)
    project = models.ForeignKey(GTDProject, on_delete=models.SET_NULL, null=True, blank=True)
    NONE = 0
    OPEN = 1
    COMPLETED = 2
    STATUS = [
        (NONE, 'None'),
        (OPEN, 'Open'),
        (COMPLETED, 'Completed'),
    ]
    status = models.SmallIntegerField(choices=STATUS, default=NONE)

    class Meta:
        ordering = ('-date_created',)
        get_latest_by = 'date_created'

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        self.body_html = markdown_to_html(self.body_markdown)
        super(GTDNote, self).save(*args, **kwargs)

    def get_absolute_url(self, *args, **kwargs):
        return reverse('gtd:note-edit', kwargs={"pk": self.pk})


class PostType(models.IntegerChoices):
    REVIEW = 0, ('review')
    GUIDE = 1, ('guide')
    HOWTO = 2, ('how-to')


class TemplateType(models.IntegerChoices):
    STORY = 0, ('story')
    GALLERY = 1, ('gallery')


class PostStatus(models.IntegerChoices):
    ASSIGNED = 0, ('Assigned')
    TURNEDIN = 1, ('turned in')
    PUBLISHED = 2, ('published')

class WiredPost(models.Model):
    # an entry in a feed
    title = models.CharField(max_length=512, blank=True, null=True)
    body = models.TextField(blank=True, null=True)
    url = models.CharField(max_length=512, blank=True, null=True)
    edit_url = models.CharField(max_length=512, blank=True, null=True)
    date_last_pub = models.DateField(blank=True, null=True)
    guid = models.CharField(max_length=512, blank=True, null=True, db_index=True)
    author = models.CharField(max_length=255, blank=True, null=True)
    post_type = models.IntegerField(choices=PostType.choices, default=PostType.GUIDE)
    template_type = models.IntegerField(choices=TemplateType.choices, default=TemplateType.STORY)
    update_frequency = models.BigIntegerField(help_text="In days")
    # products = models.ManyToManyField(ProductLink, blank=True, null=True)
    needs_update = models.BooleanField(default=False)
    is_live = models.BooleanField(default=True)
    post_status = models.IntegerField(choices=PostStatus.choices, default=PostStatus.PUBLISHED)

    class Meta:
        ordering = ('date_last_pub',)

    def __str__(self):
        return self.title

    def time_since_update(self):
        td = datetime.date.today() - self.date_last_pub
        return int(td.days)

    def set_needs_update(self):
        if self.date_last_pub:
            td = datetime.date.today() - self.date_last_pub
            if self.post_status == 0 or self.post_status == 2:
                if td.days > self.update_frequency:
                    self.needs_update = True
                    self.save()
        return ''

    def days_overdue(self):
        if self.needs_update:
            return self.time_since_update() - self.update_frequency
        else:
            return 0

    def admin_url(self):
        return format_html('<a target="_blank" href="%s">%s</a>' % (self.url, self.url))
        admin_link.short_description = 'Link'

    def get_absolute_url(self):
        return reverse('gtd:wiredpost-detail', kwargs={"pk": self.id})

    def save(self, *args, **kwargs):
        if self.date_last_pub:
            td = datetime.date.today() - self.date_last_pub
            if td.days > self.update_frequency and self.post_status == 2:
                self.needs_update = True
            else:
                self.needs_update = False
        super(WiredPost, self).save()


class WiredNote(models.Model):
    title = models.CharField(max_length=400)
    url = models.CharField(max_length=400, blank=True, null=True)
    body_markdown = models.TextField(blank=True, null=True)
    date_created = models.DateTimeField(default=timezone.now)
    post = models.ForeignKey(WiredPost, on_delete=models.CASCADE, null=True, blank=True)
    STATUS = (
        (0, 'Call In'),
        (1, 'Asked For'),
        (2, 'Coming'),
        (3, 'Testing'),
        (4, 'Done'),
        (5, 'Live'),
    )
    status = models.IntegerField(choices=STATUS, default=0)
    PLAN = (
        (0, 'For Guide'),
        (1, 'Review'),
        (2, 'Rave/Rant'),
        (3, 'No Plan'),
    )
    plan = models.IntegerField(choices=PLAN, default=0)

    class Meta:
        ordering = ('date_created', 'status')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('gtd:wirednote-edit', kwargs={"pk": self.pk})

    def save(self, *args, **kwargs):
        super(WiredNote, self).save()