from django.db import models
from django.utils.text import slugify
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator
from django.conf import settings
import os


class Category(models.Model):
    """作品分类模型"""
    name = models.CharField('分类名称', max_length=100)
    slug = models.SlugField('URL标识', max_length=100, unique=True, blank=True)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)

    class Meta:
        verbose_name = '作品分类'
        verbose_name_plural = '作品分类'
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        # 生成唯一的 slug
        if not self.slug:
            base_slug = slugify(self.name)
            if not base_slug:  # 如果 slugify 返回空字符串
                base_slug = f'category-{self.id}' if self.id else 'category'

            # 确保 slug 唯一
            slug = base_slug
            counter = 1
            while Category.objects.filter(slug=slug).exclude(pk=self.pk).exists():
                slug = f'{base_slug}-{counter}'
                counter += 1
            self.slug = slug
        super().save(*args, **kwargs)


class Artwork(models.Model):
    """摄影作品模型"""

    title = models.CharField('作品标题', max_length=200)
    description = models.TextField('作品描述', blank=True)
    slug = models.SlugField('URL标识', max_length=200, unique=True, blank=True)

    # 图片字段
    image = models.ImageField('作品图片', upload_to='artworks/%Y/%m/%d/')
    thumbnail = models.ImageField('缩略图', upload_to='thumbnails/%Y/%m/%d/', blank=True, null=True)

    # 关联字段
    category = models.ForeignKey(
        Category,
        on_delete=models.SET_NULL,
        verbose_name='作品分类',
        null=True,
        blank=True
    )

    # 元数据字段
    order = models.IntegerField('排序序号', default=0, help_text='数字越小越靠前')

    # 时间字段
    created_at = models.DateTimeField('创建时间', default=timezone.now)
    updated_at = models.DateTimeField('更新时间', auto_now=True)

    # 统计字段
    view_count = models.PositiveIntegerField('浏览次数', default=0)

    class Meta:
        verbose_name = '摄影作品'
        verbose_name_plural = '摄影作品'
        ordering = ['order', '-created_at']

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        # 生成唯一的 slug
        if not self.slug:
            base_slug = slugify(self.title)
            if not base_slug:  # 如果 slugify 返回空字符串
                base_slug = f'artwork-{self.id}' if self.id else 'artwork'

            # 确保 slug 唯一
            slug = base_slug
            counter = 1
            while Artwork.objects.filter(slug=slug).exclude(pk=self.pk).exists():
                slug = f'{base_slug}-{counter}'
                counter += 1
            self.slug = slug

        # 如果是新对象或图片被更新，生成缩略图
        if self.pk is None or 'image' in kwargs.get('update_fields', []):
            super().save(*args, **kwargs)
            self.generate_thumbnail()
        else:
            super().save(*args, **kwargs)

    def generate_thumbnail(self):
        """生成缩略图"""
        from PIL import Image
        from io import BytesIO
        from django.core.files.base import ContentFile
        import os

        if not self.image:
            return

        # 打开原图
        img = Image.open(self.image)

        # 计算目标像素总量：约90万像素（如1280x720）
        target_pixels = 900000

        # 获取原图尺寸
        width, height = img.size
        current_pixels = width * height

        # 计算缩放比例，使像素总量接近90万（但限制最大边不超过1600px）
        max_dimension = 1600

        if current_pixels <= 0:
            # 如果图片尺寸无效，使用原尺寸但限制最大边
            if width > max_dimension or height > max_dimension:
                scale = max_dimension / max(width, height)
                new_width = int(width * scale)
                new_height = int(height * scale)
                img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
        else:
            # 首先计算缩放至目标像素的比例
            scale_to_target = (target_pixels / current_pixels) ** 0.5

            # 然后检查缩放后是否超过最大边限制
            new_width_temp = int(width * scale_to_target)
            new_height_temp = int(height * scale_to_target)

            # 如果缩放后的尺寸超过最大边限制，使用最大边限制的比例
            if new_width_temp > max_dimension or new_height_temp > max_dimension:
                scale_to_max = max_dimension / max(new_width_temp, new_height_temp)
                scale = scale_to_target * scale_to_max
            else:
                scale = scale_to_target

            new_width = int(width * scale)
            new_height = int(height * scale)
            img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

        # 保存到内存                                                                                                                                                                                          
        thumb_io = BytesIO()                                                                                                                                                                                  
                                                                                                                                                                                                        
        # 保持原格式，如果是JPEG则优化                                                                                                                                                                        
        # 如果img.format为空，根据文件扩展名判断格式                                                                                                                                                          
        format_to_use = img.format                                                                                                                                                                            
        if not format_to_use:                                                                                                                                                                                 
            # 根据文件扩展名判断格式                                                                                                                                                                          
            filename = os.path.basename(self.image.name)                                                                                                                                                      
            name, ext = os.path.splitext(filename)                                                                                                                                                            
            ext = ext.lower()                                                                                                                                                                                 
        if ext in ['.jpg', '.jpeg', '.jpe', '.jfif']:                                                                                                                                                     
            format_to_use = 'JPEG'                                                                                                                                                                        
        elif ext in ['.png']:                                                                                                                                                                             
            format_to_use = 'PNG'                                                                                                                                                                         
        elif ext in ['.gif']:                                                                                                                                                                             
            format_to_use = 'GIF'                                                                                                                                                                         
        elif ext in ['.webp']:                                                                                                                                                                            
            format_to_use = 'WEBP'                                                                                                                                                                        
        else:                                                                                                                                                                                             
            # 默认使用JPEG格式                                                                                                                                                                            
            format_to_use = 'JPEG'                                                                                                                                                                        
                                                                                                                                                                                                        
        if format_to_use == 'JPEG':                                                                                                                                                                           
            img.save(thumb_io, format='JPEG', quality=85, optimize=True)                                                                                                                                      
        else:                                                                                                                                                                                                 
            img.save(thumb_io, format=format_to_use) 

        # 生成缩略图文件名
        filename = os.path.basename(self.image.name)
        name, ext = os.path.splitext(filename)
        thumb_filename = f'{name}_thumb{ext}'

        # 保存缩略图
        self.thumbnail.save(
            thumb_filename,
            ContentFile(thumb_io.getvalue()),
            save=False
        )

        super().save(update_fields=['thumbnail'])


    def increment_view_count(self):
        """增加浏览次数"""
        self.view_count += 1
        self.save(update_fields=['view_count'])

    def get_dynamic_grid_class(self):
        """根据图片宽高比动态返回网格CSS类"""
        try:
            if not self.thumbnail:
                return 'col-span-1 row-span-1'

            # 尝试从缩略图获取尺寸
            from PIL import Image
            import os

            thumb_path = self.thumbnail.path
            if not os.path.exists(thumb_path):
                return 'col-span-1 row-span-1'

            with Image.open(thumb_path) as img:
                width, height = img.size
                aspect_ratio = width / height

                # 根据宽高比返回不同的网格类
                if aspect_ratio > 1.5:  # 很宽的图片
                    return 'col-span-2 row-span-1'  # 占2列宽
                elif aspect_ratio < 0.67:  # 很高的图片
                    return 'col-span-1 row-span-2'  # 占2行高
                elif aspect_ratio > 1.2:  # 中等宽度
                    return 'col-span-2 row-span-1'  # 占2列宽
                elif aspect_ratio < 0.83:  # 中等高度
                    return 'col-span-1 row-span-2'  # 占2行高
                else:  # 接近正方形
                    return 'col-span-1 row-span-1'

        except Exception as e:
            # 发生错误时返回默认
            print(f"Error getting grid class for artwork {self.id}: {e}")
            return 'col-span-1 row-span-1'


class About(models.Model):
    """关于页面模型"""
    title = models.CharField('标题', max_length=200)
    content = models.TextField('内容')
    image = models.ImageField('图片', upload_to='about/', blank=True, null=True)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)

    class Meta:
        verbose_name = '关于页面'
        verbose_name_plural = '关于页面'

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        # 确保只有一个关于页面
        if not self.pk and About.objects.exists():
            # 如果已经存在关于页面，更新它而不是创建新的
            existing = About.objects.first()
            existing.title = self.title
            existing.content = self.content
            if self.image:
                existing.image = self.image
            existing.save()
            return existing
        super().save(*args, **kwargs)


class Comment(models.Model):
    """评论模型"""
    artwork = models.ForeignKey(Artwork, on_delete=models.CASCADE, verbose_name='作品')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='用户')
    text = models.TextField('评论内容', blank=True)
    image = models.ImageField('评论图片', upload_to='comments/%Y/%m/%d/', blank=True, null=True)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)
    is_active = models.BooleanField('是否有效', default=True)

    class Meta:
        verbose_name = '评论'
        verbose_name_plural = '评论'
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.user.username} 对 {self.artwork.title} 的评论"