from django.forms import (
    Form,
    ModelForm,
    ModelMultipleChoiceField,
    ModelChoiceField,
    ChoiceField,
    CharField,
)
from django.forms import inlineformset_factory
from django.contrib.postgres.forms import SimpleArrayField, SplitArrayField , SplitArrayWidget


from generic.forms import ExamAuthorFormMixin, ExamFormMixin, ExamGroupsFormMixin, ExamMarkerFormMixin

from .models import (
    Answer,
    UserAnswer,
    AnatomyQuestion,
    # Examination,
    BodyPart,
    #Structure,
    Region,
    Modality,
    QuestionType,
    Exam,
)
from generic.models import CidUserGroup, Examination

from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms.widgets import RadioSelect, TextInput, Textarea

from dal import autocomplete

from tinymce.widgets import TinyMCE

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout, Div
from crispy_forms.bootstrap import Accordion, AccordionGroup
from generic.widgets import ExamSearchWidget

class AnatomyAnswerForm(ModelForm):
    class Meta:
        model = UserAnswer
        fields = ("answer",)


class MarkAnatomyQuestionForm(Form):
    # correct = forms.CharField(required=False)
    # half_correct = forms.CharField(required=False)
    # incorrect = forms.CharField(required=False)
    marked_answers = CharField(required=False)


class AnatomyQuestionForm(ModelForm):

    # exams = ModelMultipleChoiceField(required=False, queryset=Exam.objects.all())

    class Media:
        # Django also includes a few javascript files necessary
        # for the operation of this form element. You need to
        # include <script src="/admin/jsi18n"></script>
        # in the template.
        css = {
            "all": ["css/widgets.css"],
        }
        # Adding this javascript is crucial
        js = ["jsi18n.js", "tesseract.min.js"]

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop(
            "user"
        )  # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
        if kwargs.get("instance"):
            # We get the 'initial' keyword argument or initialize it
            # as a dict if it didn't exist.
            initial = kwargs.setdefault("initial", {})
            # The widget for a ModelMultipleChoiceField expects
            # a list of primary key for the selected data.
            initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()]

        ModelForm.__init__(self, *args, **kwargs)

        super(AnatomyQuestionForm, self).__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_id = 'id-anatomy-question-form'
        #self.helper.form_class = 'blueForms'
        #self.helper.form_method = 'post'
        #self.helper.form_action = ''

        #self.helper.add_input(Submit('submit', 'Submit'))
        # self.fields['question'].widget.attrs = {'class': 'question-form', 'rows': 10, 'cols': 100}
        # self.fields['feedback'].widget.attrs = {'class': 'feedback-form', 'rows': 10, 'cols': 100}
        self.fields["question_type"] = ModelChoiceField(
            required=True,
            queryset=QuestionType.objects.all(),
            initial=1,
        )

        self.fields["region"] = ModelChoiceField(
            required=False,
            queryset=Region.objects.all(),
        )

        self.fields["modality"] = ModelChoiceField(
            required=True,
            queryset=Modality.objects.all(),
        )

        self.fields["examination"] = ModelChoiceField(
            required=False,
            queryset=Examination.objects.all(),
        )

        self.fields["body_part"] = ModelChoiceField(
            required=False,
            queryset=BodyPart.objects.all(),
        )

        #self.fields["answer_suggest_incorrect"] = CharField(max_length=255, required=False)

        if self.user.groups.filter(name="anatomy_checker").exists():
            exam_queryset = Exam.objects.all()
        else:
            exam_queryset = Exam.objects.filter(
                author__id=self.user.id
            ) | Exam.objects.filter(open_access=True)

        self.fields["exams"] = ModelMultipleChoiceField(
            required=False,
            queryset=exam_queryset,
            widget=ExamSearchWidget(exam_model=Exam),
        )

        # Now that all fields have been created, set the helper layout so
        # Crispy can find the referenced field names (including
        # `answer_suggest_incorrect`). Placing the layout here ensures the
        # collapse/accordion renders server-side.
        self.helper.layout = Layout(
            "question_type",
            "image",
            "description",
            # Place modality → body_part fields in a horizontal flex row
            Div(
                Div("modality", css_class="flex-fill me-2"),
                Div("region", css_class="flex-fill me-2"),
                Div("structure", css_class="flex-fill me-2"),
                Div("examination", css_class="flex-fill me-2"),
                Div("body_part", css_class="flex-fill"),
                css_class="d-flex flex-wrap align-items-start mb-2",
            ),
            "answer_help",
            Accordion(
                AccordionGroup(
                    "Suggest incorrect answers",
                    "answer_suggest_incorrect",
                    active=False,
                )
            ),
            "feedback",
            "open_access",
            "exams",
            Div(Submit("submit", "Submit"), css_class="form-group"),
        )

    def save(self, commit=True):
        # Get the unsaved Pizza instance
        instance = ModelForm.save(self, False)
        instance.save()

        old_exams = instance.exams.all()

        new_exams = self.cleaned_data["exams"]

        for exam in old_exams:
            if exam not in new_exams:
                exam.exam_questions.remove(instance)

        for exam in new_exams:
            exam.exam_questions.add(instance)

        self.save_m2m()

        return instance

    class Meta:
        model = AnatomyQuestion

        fields = [
            "question_type",
            "image",
            "description",
            "modality",
            "region",
            "structure",
            "feedback",
            "examination",
            "body_part",
            "answer_help",
            "answer_suggest_incorrect",
            "open_access",
        ]

        widgets = {
            "structure": autocomplete.ModelSelect2(url="atlas:structure-autocomplete"),
            "answer_help": TinyMCE(attrs={"cols": 80, "rows": 5}),
            "feedback": TinyMCE(attrs={"cols": 80, "rows": 5}),
        }

class AnatomyQuestionAnswerForm(ModelForm):
    class Meta:
        model = AnatomyQuestion
        fields = []

AnswerFormSet = inlineformset_factory(
    AnatomyQuestion,
    Answer,
    fields=["answer", "status"],
    widgets={
        "answer": Textarea(
            attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
        )
    },
    exclude=[],
    can_delete=True,
    extra=1,
    max_num=10,
)

AnswerUpdateFormSet = inlineformset_factory(
    AnatomyQuestion,
    Answer,
    fields=["answer", "status"],
    widgets={
        "answer": Textarea(
            attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
        )
    },
    exclude=[],
    can_delete=True,
    extra=0,
    max_num=10,
)


class ExaminationForm(ModelForm):
    class Meta:
        model = Examination
        fields = ["examination"]


class BodyPartForm(ModelForm):
    class Meta:
        model = BodyPart
        fields = ["bodypart"]


class ExamForm(ExamFormMixin, ModelForm):

    class Meta(ExamFormMixin.Meta):
        model = Exam

#class ExamAuthorForm(ModelForm):
#    class Meta:
#        model = Exam
#        fields = ["author"]
#
#    def __init__(self, *args, **kwargs):
#        ModelForm.__init__(self, *args, **kwargs)
#        self.fields["author"] = ModelMultipleChoiceField(
#            queryset=User.objects.all(),
#            widget=FilteredSelectMultiple(verbose_name="Authors", is_stacked=False),
#        )


class ExamAuthorForm(ExamAuthorFormMixin):
    class Meta(ExamAuthorFormMixin.Meta):
        model = Exam

class ExamMarkerForm(ExamMarkerFormMixin):
    class Meta(ExamMarkerFormMixin.Meta):
        model = Exam



class ExamGroupsForm(ExamGroupsFormMixin):
    class Meta(ExamGroupsFormMixin.Meta):
        model = Exam

class SuggestIncorrectAnswerForm(ModelForm):
    class Meta:
        model = AnatomyQuestion
        fields = ["answer_suggest_incorrect"]


class PrimaryAnswerForm(Form):
    existing_answer = ChoiceField(required=False, choices=[], label="Use existing answer")
    new_answer = CharField(required=False, widget=Textarea(attrs={"rows":3}), label="Or create new primary answer")

    def __init__(self, *args, **kwargs):
        question = kwargs.pop("question", None)
        super().__init__(*args, **kwargs)
        choices = [("", "-- choose existing --")]
        if question is not None:
            # Only include existing non-proposed CORRECT answers, ordered by answer text
            for a in question.answers.filter(proposed=False, status=Answer.MarkOptions.CORRECT).order_by('answer'):
                choices.append((str(a.pk), a.answer))
        self.fields["existing_answer"].choices = choices