import uuid
from pathlib import Path

from PIL import Image
from django.contrib.auth.models import User
from django.db import models
from django.db.models.fields.files import ImageFieldFile
from django.urls import reverse


# Create your models here.
class Assets(models.Model):
    name = models.CharField(max_length=768, unique=True)
    file = models.JSONField()

    def __str__(self):
        return self.name

    class Meta:
        permissions = [('upload_assets', "更新资源")]


class Tag(models.Model):
    types = {
        "depend": "依赖/整合包",
        "item": "物品/方块"
    }
    type = models.CharField(choices=types, max_length=127)
    name = models.CharField(max_length=255)
    sec_name = models.CharField(max_length=255, unique=True)
    ico = models.ImageField(upload_to='Tag', blank=True)
    description = models.TextField(blank=True, default="")
    generated = models.BooleanField(default=True, db_column='is_generated')

    class Meta:
        permissions = [('update_tag', "更新物品和依赖")]
        ordering = ['sec_name']

    def __str__(self):
        return self.name


class Record(models.Model):
    types = {
        "post": "发布",
        "delete": "删除",
        "update": "更新资源",
    }
    type = models.CharField(max_length=127, choices=types)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    time = models.DateTimeField(auto_now_add=True)
    comment = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.types[self.type]


class Choice(models.Model):
    types = {
        "mc_ver": "我的世界版本",
        "create_ver": "机械动力版本",
        "loader": "加载器",
        "working_behavior": "工作特性",
        "space_behavior": "空间特性",
        "design": "设计理念",
    }
    type = models.CharField(choices=types, max_length=127)
    name = models.CharField(max_length=255)

    class Meta:
        unique_together = [('type', 'name')]
        permissions = [('edit_choice', "修改标签")]
        ordering = ['type', '-name']

    def __str__(self):
        return self.name


class Function(models.Model):
    parent = models.ForeignKey("self", on_delete=models.SET_NULL, null=True, blank=True, related_name="parent_function")
    name = models.CharField(max_length=255)

    def __str__(self):
        f = self.parent
        name = self.name
        while f is not None:
            name = f.name + ">" + name
            f = f.parent
        return name

    class Meta:
        unique_together = [('parent', 'name')]
        permissions = [('edit_function', "修改分类")]
        ordering = ['parent__name', 'name']


class ItemIn(models.Model):
    item = models.ForeignKey(Tag, on_delete=models.CASCADE, limit_choices_to={'type': 'item'})
    post = models.ForeignKey("Post", on_delete=models.CASCADE)
    count = models.IntegerField(default=0)

    class Meta:
        ordering = ['count']


class ItemOut(models.Model):
    item = models.ForeignKey(Tag, on_delete=models.CASCADE, limit_choices_to={'type': 'item'})
    post = models.ForeignKey("Post", on_delete=models.CASCADE)
    count = models.IntegerField(default=0)

    class Meta:
        ordering = ['count']


class Version(models.Model):
    loader = models.ForeignKey(Choice, on_delete=models.CASCADE, limit_choices_to={"type": "loader"},
                               related_name="loader_version")
    mc_ver = models.ForeignKey(Choice, on_delete=models.CASCADE, limit_choices_to={"type": "mc_ver"},
                               related_name="mc_version")
    create_ver = models.ForeignKey(Choice, on_delete=models.CASCADE, limit_choices_to={"type": "create_ver"},
                                   related_name="create_version")

    class Meta:
        ordering = ['mc_ver', 'create_ver', 'loader']
        unique_together = [('mc_ver', 'create_ver', 'loader')]

    def __str__(self):
        return f'{self.loader} {self.mc_ver} {self.create_ver}'


def get_file_path(instance, filename):
    filename = f"{uuid.uuid4()}.webp"
    return Path('post') / filename


class Post(models.Model):
    version = models.ManyToManyField(Version, related_name='post_version')

    function = models.ForeignKey(Function, on_delete=models.SET_NULL, blank=True, null=True, related_name="function")
    working_behavior = models.ForeignKey(Choice, on_delete=models.SET_NULL, blank=True, null=True,
                                         related_name="working_behavior", limit_choices_to={"type": "working_behavior"})
    space_behavior = models.ForeignKey(Choice, on_delete=models.SET_NULL, blank=True, null=True,
                                       related_name="space_behavior", limit_choices_to={"type": "space_behavior"})
    design = models.ForeignKey(Choice, on_delete=models.SET_NULL, blank=True, null=True, related_name="design",
                               limit_choices_to={"type": "design"})
    depend = models.ManyToManyField(Tag, related_name="depend", blank=True, limit_choices_to={"type": "depend"})

    stress = models.IntegerField(default=0)
    delay = models.IntegerField(default=0)  # tick
    x_size = models.IntegerField(default=0)
    y_size = models.IntegerField(default=0)
    z_size = models.IntegerField(default=0)

    title = models.CharField(max_length=255, default="未命名发布")
    create_time = models.DateTimeField(auto_now=True)
    author = models.TextField(blank=True, null=True)
    cover = models.ImageField(upload_to=get_file_path, blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)

    posted = models.BooleanField(default=False)
    sender = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)

    link = models.ManyToManyField('self', blank=True)

    removed = models.BooleanField(default=False)

    def __str__(self):
        return self.title

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

    def get_absolute_url(self):
        return reverse("post", kwargs={"pk": self.pk})

    class Meta:
        permissions = [('send_post', "发布"), ('infinite_send_post', "无限发布")]


class Comment(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True)
    time = models.DateTimeField(auto_now_add=True)
    content = models.TextField(null=True)
    reply_to = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)

    def __str__(self):
        return self.content[:10] + "…"


class Verify(models.Model):
    agree = models.ManyToManyField(User, related_name="agree", blank=True)
    disagree = models.ManyToManyField(User, related_name="disagree", blank=True)
    version = models.ForeignKey(Version, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)

    class Meta:
        unique_together = (("post", "version"),)

    def __str__(self):
        return f"{self.agree.count()}/{self.disagree.count()}"


class PostImage(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    image = models.ImageField(upload_to=get_file_path)

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


def compress_img(img: ImageFieldFile):
    if img:
        with Image.open(img.path) as image:
            max_dimension = 2144
            if image.width > max_dimension or image.height > max_dimension:
                image.thumbnail((max_dimension, max_dimension))
            image.save(img.path, quality=80, optimize=True)


def get_blueprint_path(instance, filename):
    filename = f"{uuid.uuid4()}.nbt"
    return Path('blueprint') / filename


class Blueprint(models.Model):
    warns = {
        "invalid": "不合法的蓝图文件",
        'tooBig': "超过默认可上传尺寸",
        'empty': "空蓝图"
    }
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    notes = models.TextField(blank=True, null=True)
    downloads = models.IntegerField(default=0)
    size = models.IntegerField(default=0)
    inventory = models.TextField(blank=True, null=True)
    model = models.TextField(blank=True, null=True)
    file = models.FileField(upload_to=get_blueprint_path)
    warn = models.CharField(max_length=255, blank=True, null=True, choices=warns)

    def __str__(self):
        return self.name


class ActiveCode(models.Model):
    code = models.CharField(max_length=16, unique=True)
    creator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="creator")
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name="user")
    valid_time = models.DateTimeField(null=True, blank=True)
    valid = models.BooleanField(default=True)
    email = models.EmailField(null=True, blank=True)

    def __str__(self):
        return self.code

    class Meta:
        permissions = [('generate_active_code', "产生激活码")]
