from django.db import models
from django.utils.html import format_html
from django.utils.text import slugify
from django.conf import settings
from PIL import Image
import os
import uuid



def get_image_upload_path(instance, filename):
    """
    Fonction "callable" pour ImageField. 
    'instance' est l'objet (NewsArticle, etc.)
    'filename' est le nom original du fichier.
    """
    # 1. Déterminer le dossier (ex: images/newsarticles)
    # _meta.model_name est plus fiable que __class__.__name__
    folder = f"images/{instance._meta.model_name}s"

    # 2. Déterminer la base du nom (title, name ou filename)
    # getattr permet de tester plusieurs attributs proprement
    base_name = getattr(instance, 'title', getattr(instance, 'name', filename))
    slug_base = slugify(base_name)[:50] # Limité à 50 car pour un nom de fichier c'est suffisant

    # 3. Générer un ID unique et garder l'extension
    unique_id = uuid.uuid4().hex[:8]
    extension = os.path.splitext(filename)[1].lower()

    # 4. Construire le chemin final (relatif à MEDIA_ROOT)
    new_filename = f"{slug_base}-{unique_id}{extension}"
    return os.path.join(folder, new_filename)


class Imageable(models.Model):
    image = models.ImageField('Image', upload_to=get_image_upload_path, blank=True, null=True)

    # Tailles par défaut (peuvent être écrasées dans les classes enfants)
    image_sizes = [
        ("main", (626, 429)),
        ("thumbnail", (160, 110)),
    ]

    class Meta:
        abstract = True

    def create_resized_images(self):
        """
        Génère les variantes redimensionnées sur le disque.
        """
        if not self.image or not os.path.exists(self.image.path):
            return

        for label, size in self.image_sizes:
            self._generate_variant(label, size)

    def _generate_variant(self, label, size):
        """Logique interne de redimensionnement."""
        img_path = self.image.path
        img_dir, img_filename = os.path.split(img_path)
        img_name, img_ext = os.path.splitext(img_filename)
        
        variant_filename = f"{img_name}_{label}{img_ext}"
        variant_path = os.path.join(img_dir, variant_filename)

        with Image.open(img_path) as img:
            # thumbnail() garde le ratio d'aspect, contrairement à resize()
            img.thumbnail(size, Image.Resampling.LANCZOS)
            img.save(variant_path, quality=85, optimize=True)

    def get_variant_url(self, label):
        """Retourne l'URL de la variante (utilisable dans les templates)."""
        if not self.image:
            return ""
        
        # On reconstruit le nom du fichier variante
        path, filename = os.path.split(self.image.url)
        name, ext = os.path.splitext(filename)
        return f"{path}/{name}_{label}{ext}"

    def image_tag(self, label="thumbnail"):
        """Affiche l'image dans l'admin Django."""
        url = self.get_variant_url(label)
        if url:
            return format_html('<img src="{}" style="max-height: 80px; border-radius: 5px;" />', url)
        return "Pas d'image"

