from django import forms
from django.core.exceptions import ValidationError

from apps.core.forms import DateInput, DateTimeLocalInput, StyledFormMixin
from apps.core.html import plain_text, sanitize_html
from apps.medialib.models import MediaAsset
from apps.taxonomy.models import Category, Tag

from .models import Annonce, Article, ArticleImage, Status


class EditorialForm(StyledFormMixin, forms.ModelForm):
    """Champs communs + règles liées au rôle (le rédacteur ne publie ni ne met à la une)."""

    EDITOR_ONLY = ("est_a_la_une", "est_flash_info", "publie_le", "slug")

    def __init__(self, *args, user=None, **kwargs):
        self.user = user
        super().__init__(*args, **kwargs)
        self.fields["image_principale"].queryset = MediaAsset.objects.filter(type=MediaAsset.Kind.IMAGE)
        self.fields["image_principale"].widget = forms.HiddenInput()
        self.fields["publie_le"].widget = DateTimeLocalInput()
        self.fields["publie_le"].input_formats = ["%Y-%m-%dT%H:%M"]
        self.fields["slug"].required = False
        self.fields["contenu"].widget.attrs.update({"data-editor": "rich", "rows": 18})
        if user is not None and not user.is_editeur:
            for name in self.EDITOR_ONLY:
                self.fields.pop(name, None)

    def clean_contenu(self):
        html = sanitize_html(self.cleaned_data["contenu"])
        if not plain_text(html) and "<img" not in html and "<iframe" not in html:
            raise ValidationError("Le contenu est obligatoire.")
        return html


class ArticleForm(EditorialForm):
    gallery_media = forms.CharField(required=False, widget=forms.HiddenInput())

    class Meta:
        model = Article
        fields = [
            "titre", "slug", "resume", "contenu", "categorie", "tags",
            "image_principale", "legende_image", "est_a_la_une", "est_flash_info", "publie_le",
        ]
        widgets = {
            "resume": forms.Textarea(attrs={"rows": 3, "maxlength": 600}),
            "tags": forms.CheckboxSelectMultiple,
        }
        error_messages = {
            "titre": {"required": "Le titre de l'article est obligatoire."},
            "categorie": {"required": "La rubrique est obligatoire."},
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["categorie"].queryset = Category.objects.order_by("nom")
        self.fields["categorie"].empty_label = "— Choisir une rubrique —"
        self.fields["tags"].queryset = Tag.objects.order_by("nom")

    def clean_gallery_media(self):
        raw = self.cleaned_data.get("gallery_media") or ""
        ids = [int(x) for x in raw.split(",") if x.strip().isdigit()]
        return list(MediaAsset.objects.filter(pk__in=ids, type=MediaAsset.Kind.IMAGE))


class GalleryImageForm(StyledFormMixin, forms.ModelForm):
    class Meta:
        model = ArticleImage
        fields = ["legende", "ordre"]
        widgets = {"ordre": forms.NumberInput(attrs={"min": 0, "class": "w-20"})}


GalleryFormSet = forms.inlineformset_factory(
    Article, ArticleImage, form=GalleryImageForm, extra=0, can_delete=True
)


class AnnonceForm(EditorialForm):
    class Meta:
        model = Annonce
        fields = [
            "titre", "slug", "type", "annonceur", "resume", "contenu", "contact", "date_limite",
            "image_principale", "legende_image", "piece_jointe", "est_a_la_une", "publie_le",
        ]
        widgets = {
            "resume": forms.Textarea(attrs={"rows": 3}),
            "date_limite": DateInput(),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["piece_jointe"].queryset = MediaAsset.objects.all()
        self.fields["piece_jointe"].widget = forms.HiddenInput()


class ContentFilterForm(StyledFormMixin, forms.Form):
    STATUS_CHOICES = [("", "Tous (hors corbeille)")] + list(Status.choices) + [
        ("programme", "Programmé"),
        ("corbeille", "Corbeille"),
    ]
    SORT_CHOICES = [
        ("-date", "Plus récents"),
        ("date", "Plus anciens"),
        ("-publie", "Publication récente"),
        ("publie", "Publication ancienne"),
        ("titre", "Titre A→Z"),
        ("-titre", "Titre Z→A"),
        ("-vues", "Plus lus"),
        ("vues", "Moins lus"),
    ]

    q = forms.CharField(required=False, widget=forms.TextInput(attrs={"placeholder": "Rechercher un titre, un texte…"}))
    statut = forms.ChoiceField(choices=STATUS_CHOICES, required=False)
    auteur = forms.ModelChoiceField(queryset=None, required=False, empty_label="Tous les auteurs")
    du = forms.DateField(required=False, widget=DateInput(), label="Du")
    au = forms.DateField(required=False, widget=DateInput(), label="Au")
    une = forms.BooleanField(required=False, label="À la une")
    flash = forms.BooleanField(required=False, label="Flash info")
    tri = forms.ChoiceField(choices=SORT_CHOICES, required=False)
    par_page = forms.TypedChoiceField(choices=[(10, 10), (20, 20), (50, 50)], coerce=int, required=False)

    def __init__(self, *args, extra_filters=None, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        from apps.accounts.models import BACKOFFICE_ROLES, User

        self.fields["auteur"].queryset = User.objects.filter(role__in=BACKOFFICE_ROLES).order_by("name")
        if user is not None and not user.is_editeur:
            self.fields.pop("auteur")
        for name, field in (extra_filters or {}).items():
            self.fields[name] = field
        for name in extra_filters or {}:
            self.fields[name].widget.attrs.setdefault("class", "form-select")
