import time
from django.db import models
from django.utils.translation import gettext_lazy as _
from development.models import Development
from django.utils.text import slugify
from main.fields import WEBPField
from bs4 import BeautifulSoup
import readtime

from user.models import Master

CHECK_BOOLEAN = [
    (True,_("submitted")),
    (False,_("ignored")),
]

ACTIVE_BOOLEAN = [
    (True,_("active")),
    (False,_("deactive")),
]

QUESTION_BOOLEAN = [
    (True,_("yes")),
    (False,_("no")),
]


# Create your models here.
class Keyword(models.Model):
    language = models.ForeignKey("main.Language", verbose_name=_("Language"), related_name="keywords", on_delete=models.CASCADE)
    title = models.CharField(_("Title"), max_length=500, db_index=True)
    slug = models.SlugField(_("slug"), max_length=500, db_index=True, allow_unicode=True, null=True, blank=True)
    related = models.ManyToManyField("self", verbose_name=_("related"), blank=True)
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def save(self, *args, **kwargs):
        if self.title: self.slug = slugify(self.title, allow_unicode=True)
        super().save(*args, **kwargs)
    
    def __str__(self):
        return f"{self.title}"
    
    class Meta:
        verbose_name = _("Keyword")
        verbose_name_plural = _("Keywords")
        ordering = ['-id']
        
        
        
class Category(models.Model):
    title = models.CharField(_("Title"), max_length=500, db_index=True)
    slug = models.SlugField(_("slug"), max_length=500, db_index=True, unique=True, allow_unicode=True, null=True, blank=True)
    related = models.ManyToManyField("self", verbose_name=_("related"), blank=True)
    is_activate = models.BooleanField(_("active"), default=True)
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def save(self, *args, **kwargs):
        if self.title: self.slug = slugify(self.title, allow_unicode=True)
        super().save(*args, **kwargs)
    
    def __str__(self):
        return f"{self.title}"
    
    class Meta:
        verbose_name = _("Category")
        verbose_name_plural = _("Categories")
        ordering = ['-id']
        
class CategoryTranslate(models.Model):
    language = models.ForeignKey("main.Language", verbose_name=_("Language"), related_name="category_translate", on_delete=models.CASCADE)
    category = models.ForeignKey(Category, verbose_name=_("Category"), related_name="translates", on_delete=models.CASCADE)
    title = models.CharField(_("Title"), max_length=500, db_index=True)
    slug = models.SlugField(_("slug"), max_length=500, db_index=True, allow_unicode=True, null=True, blank=True)
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.category.title, allow_unicode=True)
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.title}"

    class Meta:
        verbose_name = _("Category Translate")
        verbose_name_plural = _("Category Translate")
        ordering = ['-id']


def image_news_folder(instance, filename):
    return f'news/{instance.slug}.webp'

class News(models.Model):
    development = models.ForeignKey(Development, verbose_name=_("Development"), related_name="news", on_delete=models.CASCADE, null=True, blank=True)
    
    title = models.CharField(_("Title"), max_length=500, db_index=True)
    slug = models.SlugField(_("slug"), max_length=500, db_index=True, unique=True, allow_unicode=True, null=True, blank=True)
    image = WEBPField(_("Image"), upload_to=image_news_folder, db_index=True, blank=True, null=True)
    keywords = models.ManyToManyField(Keyword, verbose_name=_("Keywords"), related_name="keyword_news", blank=True)
    category = models.ForeignKey(Category, verbose_name=_("Category"), related_name="category_news", on_delete=models.CASCADE, null=True, blank=True)
    is_featured = models.BooleanField(_("Featured"), default=False, choices=QUESTION_BOOLEAN)
    is_publish = models.BooleanField(_("Publish"), default=False)
    is_deleted = models.BooleanField(_("Deleted"), default=False)
    is_translated = models.BooleanField(_("Translated"), default=False)
    writer = models.ForeignKey(Master, verbose_name=_("Writer"), related_name="news_writers", on_delete=models.SET_NULL, null=True, blank=True)
    
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def __str__(self):
        return f"{self.title}"
    
    def save(self, *args, **kwargs):
        if self.title: self.slug = slugify(self.title, allow_unicode=True)
        super().save(*args, **kwargs)
    
    class Meta:
        verbose_name = _("News")
        verbose_name_plural = _("News")
        ordering = ["-id"]
        indexes = [
            models.Index(fields=['slug', 'title', "is_featured"])
        ]
    
class NewsTranslate(models.Model):
    language = models.ForeignKey("main.Language", verbose_name=_("Language"), related_name="news_language", on_delete=models.CASCADE)
    news = models.ForeignKey(News, verbose_name=_("News"), related_name="translates", on_delete=models.CASCADE)
    title = models.CharField(_("Title"), max_length=500, db_index=True)
    slug = models.SlugField(_("slug"), max_length=500, db_index=True, allow_unicode=True, null=True, blank=True)
    keywords = models.ManyToManyField(Keyword, verbose_name=_("Keywords"), related_name="news_translate_keywords", blank=True)
    category = models.ForeignKey(CategoryTranslate, verbose_name=_("Category"), related_name="category_news_translate", on_delete=models.CASCADE, null=True, blank=True)
    summary = models.TextField(_("Summary"), db_index=True, null=True, blank=True)
    description = models.TextField(_("Description"), null=True, blank=True)
    read_time = models.PositiveIntegerField(_("Read Time"), default=0)
    
    created_at = models.DateTimeField(_("created at"), db_index=True, auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def __str__(self):
        return f"{self.title}"
    
    def save(self, *args, **kwargs):
        self.slug = slugify(self.news.title, allow_unicode=True)
        if self.summary is None or self.summary == "":
            try: self.summary = BeautifulSoup(self.description, 'html.parser').find_all('p')[0].text
            except: pass
        if self.category is None: 
            try: self.category = self.news.category.translates.filter(language=self.language).first()
            except: pass
        if self.description is not None:
            read_time = readtime.of_html(self.description)
            self.read_time = read_time.minutes
        super().save(*args, **kwargs)
    
    class Meta:
        verbose_name = _("News Translate")
        verbose_name_plural = _("News Translate")
        ordering = ["-id"]
        constraints = [
            models.UniqueConstraint(fields=['language', 'news'], name='repeated_language_news_translate'),
        ]
    
    
class Visitor(models.Model):
    """
    Represents a visitor to a news article.
    
    The Visitor model represents a visitor to a news article in the system. It has the following fields:
    
    - `news`: A foreign key to the `News` model, representing the news article the visitor is associated with.
    - `ip`: The IP address of the visitor.
    - `user_agent`: The user agent information of the visitor (nullable).
    - `visit_time`: The time the visitor spent on the news article (nullable).
    - `unique_time`: A unique identifier for the visitor's visit (nullable).
    - `created_at`: The datetime when the visitor record was created.
    - `updated_at`: The datetime when the visitor record was last updated.
    
    The `save` method automatically sets the `visit_time` and `unique_time` fields if they are not provided.
    
    The model has a unique constraint on the `news`, `unique_time`, and `user_agent` fields to prevent repeated visits by the same user to the same news article.
    """    
    news = models.ForeignKey(News, on_delete=models.CASCADE, verbose_name=_("News"), related_name="visitors")
    
    ip = models.GenericIPAddressField(_("IP"))
    user_agent = models.TextField(_("User Agent"), null=True, blank=True)
    
    visit_time = models.FloatField(_("visit time"), null=True, blank=True)
    unique_time = models.IntegerField(_("unique time"), null=True, blank=True)
    
    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def save(self, *args, **kwargs):
        if self.visit_time is None:
            self.visit_time = time.time()
            self.unique_time = int(time.time()/1000)
        return super().save(*args, **kwargs)


    class Meta:
        verbose_name = _("Visitor")
        verbose_name_plural = _("Visitors")
        ordering = ['-id']
        constraints = [
            models.UniqueConstraint(fields=['news', 'unique_time', 'user_agent'], name='repeated_user_news_visit'),
        ]
        
        
BLOG_PROMPT = '''Give me an concise and clear article about the following subject with html tags in {language} language, only the relevant part and without html, head, body and heading tags between h2-h6 and not contain title, which is related to real estate consulting, and if possible, the name Entralon (by https://entralon.com link) will be mentioned as a real estate consultant website.
    {text}
    '''
class TitleOfBlog(models.Model):
    """
    Represents the title of a blog post.

    The TitleOfBlog model represents the title of a blog post in the system. It has the following fields:

    - `title`: The title of the blog post.
    - `description`: The description or content of the blog post.
    - `created_at`: The datetime when the blog post title was created.
    - `updated_at`: The datetime when the blog post title was last updated.

    The `__str__` method returns the title of the blog post.
    """
    title = models.CharField(_("Title"), max_length=255)
    prompt = models.TextField(_("Prompt"), default=BLOG_PROMPT)
    category = models.ForeignKey(Category, verbose_name=_("Category"), related_name="titles", on_delete=models.CASCADE, null=True, blank=True)
    is_created = models.BooleanField(_("Created"), default=False, choices=QUESTION_BOOLEAN)

    created_at = models.DateTimeField(_("created at"), auto_now_add=True)
    updated_at = models.DateTimeField(_("updated at"), auto_now=True)
    
    def __str__(self):
        return f"{self.title}"
    
    class Meta:
        verbose_name = _("Title of Blog")
        verbose_name_plural = _("Titles of Blog")
        ordering = ["-id"]