from datetime import date, datetime
from django.db import models
from django.core.files import File
from django.urls import reverse
from django.conf import settings
from django.contrib.contenttypes.fields import (
    GenericForeignKey, GenericRelation
)
from django.contrib.contenttypes.models import ContentType
# from django.contrib.postgres.fields import ArrayField

from accounts.models import User


class Topic(models.Model):
    """
    Description: A way of grouping a set of posts that may belong to
    a series of posts essays that are a part of a longer thread.
    """
    name = models.CharField(max_length=255)
    description = models.CharField(max_length=500, blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('core:topic-detail', kwargs={'topic_pk': self.pk})


class Tag(models.Model):
    """
    Description: A way of creating content themes that can group otherwise
    unrelated posts together.
    """
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def get_absolute_url(self):
        return reverse('core:tag-detail', kwargs={'pk': self.pk})

    def __str__(self):
        return self.tag

    class Meta:
        indexes = [
            models.Index(fields=['content_type', 'object_id']),
        ]


class CommentManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().select_related('author')


class Comment(models.Model):
    """
    Description: People always need a way to leave information for future
    reference
    """
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = CommentManager()

    @property
    def edited(self):
        if self.created_at.strftime('%Y%m%d%H%M%S') != self.updated_at.strftime('%Y%m%d%H%M%S'):
            return True
        else:
            return False

    def get_absolute_url(self):
        return reverse('core:comment-detail', kwargs={'pk': self.pk})

    def __str__(self):
        return f'{self.author}: {self.content}'

    class Meta:
        ordering = ['created_at']
        indexes = [
            models.Index(fields=['content_type', 'object_id']),
        ]


class PostManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(
            models.Count('comments')
        ).select_related(
            'author'
        ).prefetch_related(
            'comments'
        )


class Post(models.Model):
    """
    Description: Where the news starts
    """
    author = models.ForeignKey(
        User,
        blank=True,
        null=True,
        on_delete=models.SET_NULL
    )
    title = models.CharField(max_length=255)
    content = models.TextField(blank=True)
    topic = models.ForeignKey(
        Topic,
        blank=True,
        null=True,
        on_delete=models.SET_NULL
    )

    comments = GenericRelation(Comment, related_query_name='parent')
    recipients = models.ManyToManyField(
        User,
        blank=True,
        null=True,
        related_name='subscriptions'
    )
    tags = GenericRelation(Tag)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = PostManager()

    def get_absolute_url(self):
        return reverse('core:post-detail', kwargs={
            'topic_pk': self.topic.pk,
            'post_pk': self.pk
        })

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-updated_at']
