from django import forms

from app.models.students import Student
from app.models.subjects import Subject
from secondary.models import (
    ALevelCompetencyScale,
    ALevelComponentWeight,
    ALevelModuleAssessment,
    ALevelSubjectModule,
    ContinuousAssessmentTask,
    SecondaryCompetency,
    SecondaryComputationPolicy,
    SecondaryGradeBand,
    SubjectCompetency,
    UNEBSubmissionBatch,
)


class BaseStyledForm:
    """Apply consistent bootstrap classes to generated widgets."""

    def _apply_widget_classes(self):
        for name, field in self.fields.items():
            widget = field.widget
            if isinstance(widget, (forms.CheckboxInput, forms.CheckboxSelectMultiple)):
                continue
            classes = widget.attrs.get("class", "").strip()
            widget.attrs["class"] = f"{classes} form-control".strip()
            if isinstance(widget, forms.SelectDateWidget):
                widget.attrs["class"] = "form-control"


class SecondaryComputationPolicyForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = SecondaryComputationPolicy
        fields = [
            "name",
            "section",
            "level",
            "ca_weight",
            "exam_weight",
            "rounding_mode",
            "effective_from",
            "effective_to",
            "is_active",
        ]
        widgets = {
            "effective_from": forms.DateInput(attrs={"type": "date"}),
            "effective_to": forms.DateInput(attrs={"type": "date"}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class SecondaryGradeBandForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = SecondaryGradeBand
        fields = ["grade", "descriptor", "min_score", "max_score", "display_order"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class SecondaryCompetencyForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = SecondaryCompetency
        fields = ["code", "name", "description", "is_active"]
        widgets = {
            "description": forms.Textarea(attrs={"rows": 3}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class SubjectCompetencyForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = SubjectCompetency
        fields = ["subject", "competency", "is_core"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class ContinuousAssessmentTaskForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = ContinuousAssessmentTask
        fields = [
            "title",
            "academic_class",
            "term",
            "subject",
            "subject_competency",
            "task_type",
            "weight",
            "max_score",
            "assigned_date",
            "evidence_required",
            "uneb_eligible",
        ]
        widgets = {
            "assigned_date": forms.DateInput(attrs={"type": "date"}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class UNEBSubmissionBatchForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = UNEBSubmissionBatch
        fields = ["title", "academic_year", "section", "level", "candidate_class", "notes"]
        widgets = {
            "notes": forms.Textarea(attrs={"rows": 3}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._apply_widget_classes()


class SecondaryResultPreviewForm(BaseStyledForm, forms.Form):
    student = forms.ModelChoiceField(queryset=Student.objects.none())
    subject = forms.ModelChoiceField(queryset=Subject.objects.none())
    exam_score = forms.DecimalField(max_digits=6, decimal_places=2, min_value=0, max_value=100)
    policy = forms.ModelChoiceField(queryset=SecondaryComputationPolicy.objects.none(), required=False)

    def __init__(self, *args, **kwargs):
        student_qs = kwargs.pop("student_qs", None)
        subject_qs = kwargs.pop("subject_qs", None)
        policy_qs = kwargs.pop("policy_qs", None)
        super().__init__(*args, **kwargs)
        self.fields["student"].queryset = student_qs if student_qs is not None else self.fields["student"].queryset
        self.fields["subject"].queryset = subject_qs if subject_qs is not None else self.fields["subject"].queryset
        self.fields["policy"].queryset = policy_qs if policy_qs is not None else self.fields["policy"].queryset
        self._apply_widget_classes()


class ALevelCompetencyScaleForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = ALevelCompetencyScale
        fields = [
            "policy",
            "code",
            "descriptor",
            "point_value",
            "min_weighted_point",
            "max_weighted_point",
            "display_order",
        ]

    def __init__(self, *args, **kwargs):
        policy_qs = kwargs.pop("policy_qs", None)
        super().__init__(*args, **kwargs)
        if policy_qs is not None:
            self.fields["policy"].queryset = policy_qs
        self._apply_widget_classes()


class ALevelComponentWeightForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = ALevelComponentWeight
        fields = ["policy", "subject", "component_type", "weight", "is_required"]

    def __init__(self, *args, **kwargs):
        policy_qs = kwargs.pop("policy_qs", None)
        subject_qs = kwargs.pop("subject_qs", None)
        super().__init__(*args, **kwargs)
        if policy_qs is not None:
            self.fields["policy"].queryset = policy_qs
        if subject_qs is not None:
            self.fields["subject"].queryset = subject_qs
        self._apply_widget_classes()


class ALevelSubjectModuleForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = ALevelSubjectModule
        fields = ["subject", "code", "name", "module_order", "is_active"]

    def __init__(self, *args, **kwargs):
        subject_qs = kwargs.pop("subject_qs", None)
        super().__init__(*args, **kwargs)
        if subject_qs is not None:
            self.fields["subject"].queryset = subject_qs
        self._apply_widget_classes()


class ALevelModuleAssessmentForm(BaseStyledForm, forms.ModelForm):
    class Meta:
        model = ALevelModuleAssessment
        fields = [
            "policy",
            "student",
            "subject",
            "module",
            "component_type",
            "competency_code",
            "points_awarded",
            "attempt_no",
            "assessed_on",
            "notes",
        ]
        widgets = {
            "assessed_on": forms.DateInput(attrs={"type": "date"}),
            "notes": forms.Textarea(attrs={"rows": 2}),
        }

    def __init__(self, *args, **kwargs):
        policy_qs = kwargs.pop("policy_qs", None)
        student_qs = kwargs.pop("student_qs", None)
        subject_qs = kwargs.pop("subject_qs", None)
        module_qs = kwargs.pop("module_qs", None)
        super().__init__(*args, **kwargs)
        if policy_qs is not None:
            self.fields["policy"].queryset = policy_qs
        if student_qs is not None:
            self.fields["student"].queryset = student_qs
        if subject_qs is not None:
            self.fields["subject"].queryset = subject_qs
        if module_qs is not None:
            self.fields["module"].queryset = module_qs
        self._apply_widget_classes()


class ALevelResultPreviewForm(BaseStyledForm, forms.Form):
    student = forms.ModelChoiceField(queryset=Student.objects.none())
    subject = forms.ModelChoiceField(queryset=Subject.objects.none())
    policy = forms.ModelChoiceField(queryset=SecondaryComputationPolicy.objects.none(), required=False)

    def __init__(self, *args, **kwargs):
        student_qs = kwargs.pop("student_qs", None)
        subject_qs = kwargs.pop("subject_qs", None)
        policy_qs = kwargs.pop("policy_qs", None)
        super().__init__(*args, **kwargs)
        if student_qs is not None:
            self.fields["student"].queryset = student_qs
        if subject_qs is not None:
            self.fields["subject"].queryset = subject_qs
        if policy_qs is not None:
            self.fields["policy"].queryset = policy_qs
        self._apply_widget_classes()
