from translated_fields import language_code_formfield_callback

from django import forms
from django.forms.models import inlineformset_factory
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from .models import Election, Option, Question
from .utils import check_csv


class ElectionForm(forms.ModelForm):
    formfield_callback = language_code_formfield_callback

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data["start_date"] < timezone.now():
            self.add_error(
                "start_date", _("Impossible de faire débuter l'élection dans le passé")
            )
        elif cleaned_data["start_date"] >= cleaned_data["end_date"]:
            self.add_error(
                "end_date", _("Impossible de terminer l'élection avant de la commencer")
            )

        if self.instance.sent_mail and not cleaned_data["restricted"]:
            self.add_error(
                "restricted",
                _(
                    "Le mail d'annonce a déjà été envoyé, il n'est pas possible "
                    "d'ouvrir l'élection à tout le monde"
                ),
            )
        return cleaned_data

    class Meta:
        model = Election
        fields = [
            *Election.name.fields,
            "start_date",
            "end_date",
            *Election.description.fields,
            "restricted",
            *Election.vote_restrictions.fields,
        ]
        widgets = {
            "description_en": forms.Textarea(
                attrs={"rows": 4, "class": "is-family-monospace"}
            ),
            "description_fr": forms.Textarea(
                attrs={"rows": 4, "class": "is-family-monospace"}
            ),
            "vote_restrictions_en": forms.Textarea(
                attrs={"rows": 4, "class": "is-family-monospace"}
            ),
            "vote_restrictions_fr": forms.Textarea(
                attrs={"rows": 4, "class": "is-family-monospace"}
            ),
        }


class UploadVotersForm(forms.Form):
    csv_file = forms.FileField(label=_("Sélectionnez un fichier .csv"))

    def clean_csv_file(self):
        csv_file = self.cleaned_data["csv_file"]
        if csv_file.name.lower().endswith(".csv"):
            for error in check_csv(csv_file):
                self.add_error(None, error)
        else:
            self.add_error(
                None,
                _("Extension de fichier invalide, il faut un fichier au format CSV."),
            )
        csv_file.seek(0)
        return csv_file


class VoterMailForm(forms.Form):
    objet = forms.CharField(label=_("Objet"))
    message = forms.CharField(widget=forms.Textarea)


class QuestionForm(forms.ModelForm):
    formfield_callback = language_code_formfield_callback

    class Meta:
        model = Question
        fields = [*Question.text.fields, "type"]
        widgets = {"text_fr": forms.TextInput, "text_en": forms.TextInput}


class OptionForm(forms.ModelForm):
    formfield_callback = language_code_formfield_callback

    class Meta:
        model = Option
        fields = [*Option.text.fields, "abbreviation"]
        widgets = {"text_fr": forms.TextInput, "text_en": forms.TextInput}
        help_texts = {
            "abbreviation": _(
                "L'abréviation est optionnelle et sert à identifier plus facilement les "
                "différentes options. Elle est affiché sans espaces et en majuscules."
            )
        }


class DeleteVoteForm(forms.Form):
    def __init__(self, **kwargs):
        voter = kwargs.pop("voter", None)
        super().__init__(**kwargs)
        if voter is not None:
            self.fields["delete"].label = _("Supprimer le vote de {} ({}) ?").format(
                voter.full_name, voter.base_username
            )

    delete = forms.ChoiceField(
        label=_("Supprimer"), choices=(("non", _("Non")), ("oui", _("Oui")))
    )


class SelectVoteForm(forms.ModelForm):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # We set the option's text as the label for the checkbox
        instance = kwargs.get("instance", None)
        if instance is not None:
            self.fields["selected"].label = str(instance)

    selected = forms.BooleanField(required=False)

    class Meta:
        model = Option
        fields = []
        exclude = ["voters"]


class RankVoteForm(forms.ModelForm):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # We set the option's text as the label for the rank
        instance = kwargs.get("instance", None)
        if instance is not None:
            self.fields["rank"].label = str(instance)

    rank = forms.IntegerField(required=False)

    class Meta:
        model = Option
        fields = []
        exclude = ["voters"]


class BallotFormset:
    select = inlineformset_factory(
        Question, Option, extra=0, form=SelectVoteForm, can_delete=False
    )

    rank = inlineformset_factory(
        Question, Option, extra=0, form=RankVoteForm, can_delete=False
    )