from typing import Any

from django import forms
from django.core.files.uploadedfile import UploadedFile
from django.utils.datastructures import MultiValueDict

from .schemas import (
    FieldError,
    FieldErrorList,
    FormValidation,
    FormsetValidation,
)
from .schema_utils import create_form_instance


def validate_form_instance(
    form_class: type[forms.BaseForm],
    data: dict,
    files: MultiValueDict[str, UploadedFile] | None = None,
    **kwargs: Any,
) -> tuple[forms.BaseForm, FormValidation]:
    """
    Build a form instance and return (form, structured_validation_errors).
    """
    form = create_form_instance(form_class, data=data, files=files, initial=data, **kwargs)

    # Run validation
    form.is_valid()

    validation = FormValidation(
        errors=[
            FieldErrorList(
                field=field_name,
                errors=[
                    FieldError(
                        message=str(e.message) if hasattr(e, 'message') else str(e),
                        code=getattr(e, "code", None),
                    )
                    for e in field_errors.as_data()
                ],
            )
            for field_name, field_errors in form.errors.items()
        ]
    )
    return form, validation


def build_formset_validation(formset: forms.BaseFormSet) -> FormsetValidation:
    """
    Turn a Django formset into a FormsetValidation structure.
    """
    return FormsetValidation(
        general=[str(e) if e else "" for e in formset.non_form_errors()],
        per_form=[
            FormValidation(
                errors=[
                    FieldErrorList(
                        field=field_name,
                        errors=[
                            FieldError(
                                message=str(e.message) if hasattr(e, 'message') else str(e),
                                code=getattr(e, "code", None),
                            )
                            for e in field_errors.as_data()
                        ],
                    )
                    for field_name, field_errors in form.errors.items()
                ]
            )
            for form in formset
        ],
    )
