import time
from typing import Iterable
import uuid
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import Permission
from geo_location.models import City, Country
from main.fields import WEBPField
from django.utils.text import slugify
from django_ckeditor_5.fields import CKEditor5Field
from django.contrib.auth import get_user_model

# Create your models here.

User = get_user_model()

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

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

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


def link_folder(instance, filename):
    return f'links/{uuid.uuid4().hex}.webp'

USE_FOR = [
    ("master", _("master page")),
    ("customer", _("customer page")),
    ("main", _("main pages")),
]

class Links(models.Model):
    name = models.CharField(_("name"), max_length=100, null=True, blank=True)
    slug = models.SlugField(_("slug"), max_length=100, null=True, blank=True)
    link = models.CharField(_("link"), max_length=250, default="#")
    views = models.CharField(_("view name"), max_length=500, null=True, blank=True)
    parent = models.ForeignKey('self', verbose_name=_("parent"), related_name="sub_links", on_delete=models.RESTRICT, blank=True, null=True)
    related_link = models.ForeignKey('self', verbose_name=_("related link"), related_name="related_links", on_delete=models.RESTRICT, blank=True, null=True)
    icon = models.CharField(_("icon"), max_length=250, default="fa-solid fa-sliders")
    priority = models.SmallIntegerField(_("priority"), default=100)
    permission = models.ForeignKey(Permission, verbose_name=_("Permission"), on_delete=models.RESTRICT, null=True, blank=True)
    show = models.BooleanField(_("show/hide"), default=True)
    use_for = models.CharField(_("use For"), max_length=50, choices=USE_FOR)
    
    def save(self, *args, **kwargs):
        if self.name: self.slug = slugify(self.name, allow_unicode=True)
        if self.name is not None:
            if per := self.permission:
                per.name = self.name
                per.save()
        super().save(*args, **kwargs)

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

    class Meta:
        verbose_name = _("link")
        verbose_name_plural = _("link")
        ordering = ['priority', 'use_for', 'views']


class Menus(models.Model):
    name = models.CharField(_("name"), max_length=100)
    slug = models.SlugField(_("slug"), max_length=100, null=True, blank=True)
    links = models.ManyToManyField(Links, verbose_name=_("links"), related_name="menu_link")
    use_for = models.CharField(_("use For"), max_length=50, choices=USE_FOR)
    
    def save(self, *args, **kwargs):
        if self.name: self.slug = slugify(self.name, allow_unicode=True)
        super().save(*args, **kwargs)
    
    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _("menu")
        verbose_name_plural = _("menu")
        ordering = ['use_for']


def image_language_folder(instance, filename):
    return f'languages/{instance.code}.webp'

class Language(models.Model):
    name = models.CharField(_("Name"), max_length=150)
    code = models.CharField(_("Code"), max_length=10)
    flag = WEBPField(_("Flag"), upload_to=image_language_folder, blank=True, null=True)
    
    is_active = models.BooleanField(_("active"), default=False)
        
    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.name}"
    
    class Meta:
        verbose_name = _("Language")
        verbose_name_plural = _("Languages")
        ordering = ["name"]
        


class FooterMenu(models.Model):
    name = models.CharField(_("name"), max_length=100, null=True, blank=True)
    link = models.CharField(_("link"), max_length=250, default="#")
    priority = models.SmallIntegerField(_("priority"), default=0)
    is_active = models.BooleanField(_("show/hide"), default=True)
    
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

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

    class Meta:
        verbose_name = _("Footer Menu")
        verbose_name_plural = _("Footer Menu")
        ordering = ['priority']

class FooterMenuTranslate(models.Model):
    language = models.ForeignKey(Language, verbose_name=_("language"), on_delete=models.RESTRICT)
    footer_menu = models.ForeignKey(FooterMenu, verbose_name=_("footer menu"), on_delete=models.CASCADE, related_name="translates")
    name = models.CharField(_("name"), max_length=100, null=True, blank=True)

    def __str__(self):
        return f"{self.name}"
    
    class Meta:
        verbose_name = _("Footer Menu Translate")
        verbose_name_plural = _("Footer Menu Translate")
        ordering = ["footer_menu", 'name']

def image_site_settings_folder(instance, filename):
    return f'settings/{uuid.uuid4().hex}.webp'

class SiteSettings(models.Model): 
    title = models.CharField(_("Title"), max_length=150)
    site_name = models.CharField(_("site name"), max_length=150)
        
    site_url = models.URLField(_("site url"), max_length=255, default="https://entralon.com")
    files_prefix_url = models.CharField(_("files prefix"), max_length=250, default="https://files.entralon.com")

    fav_icon = WEBPField(_("fav icon"), upload_to=image_site_settings_folder, null=True, blank=True)
    main_logo = WEBPField(_("main logo"), upload_to=image_site_settings_folder, null=True, blank=True)
    mobile_logo = WEBPField(_("mobile logo"), upload_to=image_site_settings_folder, null=True, blank=True)
    
    can_user_login = models.BooleanField(_("can user login"), default=True)
    can_user_register = models.BooleanField(_("can user register"), default=True)
    can_admin_login = models.BooleanField(_("can admin login"), default=True)
    
    use_recaptcha = models.BooleanField(_("use recaptcha"), default=False)
    recaptcha_key = models.CharField(_("recaptcha key"), max_length=150, null=True, blank=True)
    recaptcha_secret = models.CharField(_("recaptcha secret"), max_length=150, null=True, blank=True)
    
    is_translated = models.BooleanField(_("is translated"), default=False)
    
    main_theme_address = models.CharField(_("main theme address"), max_length=250, default="", blank=True)
    master_theme_address = models.CharField(_("master theme address"), max_length=250, default="", blank=True)
    
    main_menu = models.ForeignKey(Menus, related_name='main_menu', verbose_name=_("main menu"), on_delete=models.RESTRICT, null=True, blank=True)
    master_menu = models.ForeignKey(Menus, related_name='master_menu', verbose_name=_("master menu"), on_delete=models.RESTRICT, null=True, blank=True)
    
    default_news_image = WEBPField(_("Default news image"), upload_to=image_site_settings_folder, default="blank/image-placeholder.webp")
    default_developer_image = WEBPField(_("Default developer image"), upload_to=image_site_settings_folder, default="blank/image-placeholder.webp")
    default_development_image = WEBPField(_("Default development image"), upload_to=image_site_settings_folder, default="blank/image-placeholder.webp")
    
    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 = _("Site Settings")
        verbose_name_plural = _("Site Settings")
        ordering = ["-id"]
        
class SettingTranslate(models.Model):
    site_settings = models.ForeignKey(SiteSettings, on_delete=models.CASCADE, related_name="translates")
    language = models.ForeignKey(Language, on_delete=models.CASCADE, related_name="site_settings_translates")
    site_name = models.CharField(_("site name"), max_length=150)
    short_description = models.CharField(_("short description"), max_length=255, null=True, blank=True)
    description = models.TextField(_("Description"), null=True, blank=True)
    address = models.CharField(_("Address"), max_length=500)
    address_locality = models.CharField(_("Address locality"), max_length=500, null=True, blank=True)
    address_country = models.CharField(_("Address country"), max_length=500, null=True, blank=True)
    keywords = models.TextField(_("Keywords"), null=True, blank=True)
    phone_number = models.CharField(_("phone number"), max_length=150)
    email = models.EmailField(_("email"), max_length=150)
    
    development_list_title = models.CharField(_("Development list title"), max_length=250, null=True, blank=True)
    development_search_title = models.CharField(_("Development search title"), max_length=250, null=True, blank=True)
    development_list_description = models.TextField(_("Development list description"), null=True, blank=True)
    
    developer_list_title = models.CharField(_("Developer list title"), max_length=250, null=True, blank=True)
    developer_search_title = models.CharField(_("Developer search title"), max_length=250, null=True, blank=True)
    developer_list_description = models.TextField(_("Developer list description"), null=True, blank=True)
    
    blog_list_title = models.CharField(_("Blog list title"), max_length=250, null=True, blank=True)
    blog_search_title = models.CharField(_("Blog search title"), max_length=250, null=True, blank=True)
    blog_list_description = models.TextField(_("Blog list description"), null=True, blank=True)
    
    
    rules = models.TextField(_("Rules"), null=True, blank=True)
    about_us = models.TextField(_("About us"), null=True, blank=True)
    about_us_2 = models.TextField(_("About us 2"), null=True, blank=True)
    about_us_home = models.TextField(_("About us in home"), null=True, blank=True)
    privacy_policy = models.TextField(_("Privacy policy"), null=True, blank=True)
    terms_of_use = models.TextField(_("Terms of use"), null=True, blank=True)
    privacy_notice = models.TextField(_("privacy notice"), null=True, blank=True)
    
    home_seo_text = models.TextField(_("Home seo text"), 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.site_name}"
    
    class Meta:
        verbose_name = _("Site Settings translate")
        verbose_name_plural = _("Site Settings translates")
        ordering = ["-id"]

class Faq(models.Model):
    question = models.CharField(_("Question"), max_length=250)
    answer = models.TextField(_("Answer"))

    is_active = models.BooleanField(_("active"), default=False)
    is_translated = models.BooleanField(_("translated"), default=False)

    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.question}"

    class Meta:
        verbose_name = _("FAQ")
        verbose_name_plural = _("FAQs")
        ordering = ["-id"]
        
class FaqTranslate(models.Model):
    faq = models.ForeignKey(Faq, on_delete=models.CASCADE, related_name="translates")
    language = models.ForeignKey(Language, on_delete=models.CASCADE, related_name="faq_translations")
    question = models.CharField(_("Question"), max_length=250)
    answer = models.TextField(_("Answer"))
    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.question}"
    
    class Meta:
        verbose_name = _("FAQ Translation")
        verbose_name_plural = _("FAQ Translations")
        ordering = ["-id"]
        unique_together = ["faq", "language"]
        
        
class RequestCallBack(models.Model):
    first_name = models.CharField(_("Name"), max_length=150, null=True, blank=True)
    last_name = models.CharField(_("Last Name"), max_length=150, null=True, blank=True)
    phone_number = models.CharField(_("Phone Number"), max_length=150)
    email = models.EmailField(_("Email"), max_length=150, null=True, blank=True)
    message = models.TextField(_("Message"), null=True, blank=True)
    date = models.CharField(_("Date"), max_length=25, null=True, blank=True)
    page_url = models.URLField(_("page url"))
    development = models.ForeignKey("development.Development", on_delete=models.CASCADE, related_name="request_call_backs", null=True, blank=True)
    flat = models.ForeignKey("development.Flat", on_delete=models.CASCADE, related_name="request_call_backs", null=True, blank=True)    
    developer = models.ForeignKey("developer.Developer", on_delete=models.CASCADE, related_name="request_call_backs", null=True, blank=True)
    bedroom_num = models.CharField(_("bedroom number"), max_length=150, null=True, blank=True)
    budget = models.CharField(_("Budget"), max_length=150, null=True, blank=True)
    purpose = models.CharField(_("Purpose"), max_length=150, null=True, blank=True)
    payment_method = models.CharField(_("Payment Method"), max_length=150, null=True, blank=True)
    time_to_move = models.CharField(_("Time to move"), max_length=150, null=True, blank=True)
    language = models.CharField(_("Language"), max_length=150, null=True, blank=True)
    is_read = models.BooleanField(_("Read"), default=False)
    is_checked = models.BooleanField(_("Checked"), default=False)
    send_to_bitrix = models.BooleanField(_("Send to bitrix"), default=False)
    send_time = models.FloatField(_("Send time"), null=True, blank=True)
    
    whatsapp_chat = models.BooleanField(_("Whatsapp chat"), default=False)
    telegram_chat = models.BooleanField(_("Telegram chat"), default=False)
    
    utm_campaign = models.CharField(_("UTM Campaign"), max_length=255, null=True, blank=True)
    utm_source = models.CharField(_("UTM Source"), max_length=255, null=True, blank=True)
    utm_content = models.CharField(_("UTM Content"), max_length=255, null=True, blank=True)
    utm_medium = models.CharField(_("UTM Medium"), max_length=255, 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.development is not None:
            if self.developer is None:
                self.developer = self.development.developer
        if self.flat is not None:
            if self.development is None:
                self.development = self.flat.development
            if self.developer is None:
                self.developer = self.flat.development.developer
            if self.bedroom_num is None:
                self.bedroom_num = self.flat.bedrooms_num
        return super().save(*args, **kwargs)

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

    class Meta:
        verbose_name = _("Request Call Back")
        verbose_name_plural = _("Request Call Backs")
        ordering = ["-id"]
        
class ContactUs(models.Model):
    name = models.CharField(_("Name"), max_length=150)
    phone_number = models.CharField(_("Phone Number"), max_length=150)
    email = models.EmailField(_("Email"), max_length=150)
    message = models.TextField(_("Message"), null=True, blank=True)
    
    def __str__(self):
        return f"{self.name}"

    class Meta:
        verbose_name = _("Contact Us")
        verbose_name_plural = _("Contact Us")
        ordering = ["-id"]
        
class SubscribeNewsletter(models.Model):
    email = models.EmailField(_("Email"), unique=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.email}"

    class Meta:
        verbose_name = _("Subscribe Newsletter")
        verbose_name_plural = _("Subscribe Newsletters")
        ordering = ["-id"]

class ErrorLog(models.Model):
    url = models.CharField(_("url"), max_length=255, null=True, blank=True)
    location = models.CharField(_("location"), max_length=255, null=True, blank=True)
    type = models.CharField(_("type"), max_length=255, null=True, blank=True)
    error = models.TextField(_("error"))
    unique_time = models.IntegerField(_("unique time"), default=0)
    number = models.IntegerField(_("number"), default=0)
    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.id is None:
            self.unique_time = int(time.time()/1000)
        return super().save(*args, **kwargs)

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

    class Meta:
        verbose_name = _("Error Log")
        verbose_name_plural = _("Error Logs")
        ordering = ["-id"]
        constraints = [
            models.UniqueConstraint(fields=["location", "type", "unique_time"], name='repeated_error_log_type_location_time'),
        ]

class FilterType(models.Model):
    name = models.CharField(_("name"), max_length=255, unique=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.name}"
    
    class Meta:
        verbose_name = _("Filter List Type")
        verbose_name_plural = _("Filter List Types")
        ordering = ["name"]
        
class FilterElement(models.Model):
    language = models.CharField(_("language"), max_length=5)
    name = models.CharField(_("name"), max_length=255)
    slug = models.SlugField(_("slug"), max_length=255)
    country = models.SlugField(_("country"), max_length=255)
    city = models.SlugField(_("city"), max_length=255, null=True, blank=True)
    type = models.ForeignKey(FilterType, on_delete=models.CASCADE, verbose_name=_("type"), related_name="filter_element")
    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.name}"
    
    class Meta:
        verbose_name = _("Filter Element")
        verbose_name_plural = _("Filter Elements")
        ordering = ["slug", "name"]
        constraints = [
            models.UniqueConstraint(fields=["language", "slug", "country", "city", "type"], name='repeated_filter_element_type_country_city'),
        ]
        

class FilterList(models.Model):
    language = models.ForeignKey(Language, on_delete=models.CASCADE, verbose_name=_("language"), related_name="filter_list")
    country = models.ForeignKey(Country, on_delete=models.CASCADE, verbose_name=_("country"), related_name="filter_list")
    city = models.ForeignKey(City, on_delete=models.CASCADE, verbose_name=_("city"), related_name="filter_list", null=True, blank=True)
    
    station = models.ManyToManyField(FilterElement, verbose_name=_("stations"), related_name="stations", blank=True)
    district = models.ManyToManyField(FilterElement, verbose_name=_("districts"), related_name="districts", blank=True)
    postcode = models.ManyToManyField(FilterElement, verbose_name=_("postcodes"), related_name="postcodes", blank=True)
    bedroom = models.ManyToManyField(FilterElement, verbose_name=_("bedrooms"), related_name="bedrooms", blank=True)
    area = models.ManyToManyField(FilterElement, verbose_name=_("areas"), related_name="areas", blank=True)
    zone = models.ManyToManyField(FilterElement, verbose_name=_("zones"), related_name="zones", blank=True)
    key_feature = models.ManyToManyField(FilterElement, verbose_name=_("key features"), related_name="key_features", blank=True)
    payment_option = models.ManyToManyField(FilterElement, verbose_name=_("payment options"), related_name="payment_options", blank=True)
    completion_date = models.ManyToManyField(FilterElement, verbose_name=_("completion dates"), related_name="completion_dates", blank=True)
    building_type = models.ManyToManyField(FilterElement, verbose_name=_("building types"), related_name="building_types", blank=True)
    min_price = models.ForeignKey(FilterElement, verbose_name=_("min price"), related_name="min_prices", on_delete=models.CASCADE, null=True, blank=True)
    max_price = models.ForeignKey(FilterElement, verbose_name=_("max price"), related_name="max_prices", on_delete=models.CASCADE, 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.language} {self.country} {self.city}"
    
    class Meta:
        verbose_name = _("Filter List")
        verbose_name_plural = _("Filter List")
        ordering = ["id"]
        constraints = [
            models.UniqueConstraint(fields=["language", "country", "city"], name='repeated_filter_list_language_country_city'),
        ]

AI_MODELS = [
    ("gpt-4o", "gpt 4o"),
    ("chatgpt-4o-latest", "chatgpt 4o latest"),
    ("gpt-4o-mini", "gpt 4o mini"),
    ("o1", "o1"),
    ("o1-mini", "o1 mini"),
]


class PromptChecker(models.Model):
    # user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_("user"), related_name="prompt_checker")
    name = models.CharField(_("name"), max_length=255, null=True, blank=True)
    system_prompt = models.TextField(_("system prompt"), default="You are an experienced real estate consultant with deep market knowledge.")
    user_prompt = models.TextField(_("user prompt"))
    ai_model = models.CharField(_("ai model"), max_length=255, choices=AI_MODELS, default="gpt-4o-mini")
    temperature = models.FloatField(_("temperature"), default=0.7)
    
    response = models.TextField(_("response"), 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.name}"
    
    class Meta:
        verbose_name = _("Prompt Checker")
        verbose_name_plural = _("Prompt Checkers")
        ordering = ["id"]
        
        
class SiteMapType(models.Model):
    name = models.CharField(_("name"), max_length=255, null=True, blank=True)
    title = models.CharField(_("title"), max_length=255, null=True, blank=True)
    language = models.ForeignKey(Language, on_delete=models.CASCADE, verbose_name=_("language"), related_name="site_map_types")
    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.name}"

    class Meta:
        verbose_name = _("Site Map Type")
        verbose_name_plural = _("Site Map Types")
        ordering = ["id"]
        
        
class SiteMap(models.Model):
    type = models.ForeignKey(SiteMapType, on_delete=models.CASCADE, verbose_name=_("site map type"), related_name="site_maps")
    language = models.ForeignKey(Language, on_delete=models.CASCADE, verbose_name=_("language"), related_name="site_maps")
    name = models.CharField(_("name"), max_length=255, null=True, blank=True)
    url = models.CharField(_("link"), max_length=255, null=True, blank=True)
    priority = models.FloatField(_("priority"), null=True, blank=True)
    last_modified = models.DateTimeField(_("last modified"), null=True, blank=True)
    change_frequency = models.CharField(_("change frequency"), max_length=255, 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.name}"
    
    class Meta:
        verbose_name = _("Site Map")
        verbose_name_plural = _("Site Maps")
        ordering = ["type", 'priority', "id"]
        constraints = [
            models.UniqueConstraint(fields=["type", "language", "url"], name='repeated_error_site_map_type_language_url'),
        ]