from django.contrib.auth.forms import gettext as _
from django.db import models


from app.utils.models import BaseModel
from users.models import UserSettings


from simple_history.models import HistoricalRecords


class ItemBase(BaseModel):
    class Meta:
        abstract = True

    class Serialization(BaseModel.Serialization):
        excluded_fields = BaseModel.Serialization.excluded_fields + ["author"]
        excluded_fields_edit = BaseModel.Serialization.excluded_fields_edit + ["author"]

    author = models.ForeignKey(UserSettings, on_delete=models.PROTECT)
    history = HistoricalRecords(inherit=True, user_model=UserSettings)

    @property
    def _history_user(self):
        return self.author

    @_history_user.setter
    def _history_user(self, value):
        self.author = value


class ItemType(ItemBase):
    pass


class ItemRelation(ItemBase):
    parent = models.ForeignKey("items.Item", on_delete=models.CASCADE, related_name="children")
    child = models.ForeignKey("items.Item", on_delete=models.CASCADE, related_name="parents")

    properties = models.ManyToManyField("items.Property", through="items.RelationProperty", related_name="relations")


class Item(ItemBase):
    name = models.TextField(max_length=2048)
    description = models.TextField(max_length=2048)
    type = models.ForeignKey(ItemType, on_delete=models.PROTECT)

    relations = models.ManyToManyField(
        "items.Item",
        through=ItemRelation,
    )

    properties = models.ManyToManyField(
        "items.Property",
        through="LinkedProperty",
        related_name="items",
    )


class PropertyType(models.TextChoices):
    TEXT = "text", _("Text")
    DATE = "date", _("Date")
    DATETIME = "datetime", _("Date & time")
    TIME = "time", _("Time")
    DURATION = "duration", _("Duration")
    UUID = "uuid", _("UUID")
    NUMBER = "number", _("Number")
    FLOAT = "float", _("Float")
    BOOLEAN = "boolean", _("Boolean")
    EMAIL = "email", _("Email")
    IPV4 = "ipv4", _("IPv4 address")
    IPV6 = "ipv6", _("IPv6 address")
    JSON = "json", _("JSON")

    # TODO: Add more property types (location, etc)


class Property(ItemBase):
    type = models.CharField(max_length=32, choices=PropertyType.choices, default=PropertyType.TEXT)


class BaseLinkedProperty(ItemBase):
    class Meta:
        abstract = True

    class Serialization(ItemBase.Serialization):
        dynamic_field_type = ItemBase.Serialization.dynamic_field_type + ["value"]

    class Encryption(ItemBase.Encryption):
        fields = ItemBase.Encryption.fields + ["value"]

    property = models.ForeignKey(Property, on_delete=models.CASCADE)

    # Value is encrypted too
    value = models.TextField(max_length=2048)


class LinkedProperty(BaseLinkedProperty):
    item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True, related_name="linked_properties")


class RelationProperty(BaseLinkedProperty):
    relation = models.ForeignKey(
        ItemRelation,
        on_delete=models.CASCADE,
        null=True,
        related_name="relation_properties",
    )
