# (c) cavaliba.com - data - forms.py

from django import forms
from django.conf import settings
from django.utils.translation import gettext as _

CSV_SEPARATOR_CHOICES = (
    (",", ","),
    (";", ";"),
    ("|", "|"),
)

BLANK_CHOICE = ("", "-----------")


class ImportForm(forms.Form):
    """Unified Import Tool form: file upload plus Common / CSV-specific /
    Advanced options. force_action/force_schema are only declared on the
    form when is_admin=True is passed to __init__ - a non-admin's bound
    instance never has these fields at all, so a crafted POST value for
    either one can never reach cleaned_data no matter what is submitted."""

    file = forms.FileField(
        widget=forms.ClearableFileInput(attrs={"class": "form-control cv-file-input"}),
        label=_("File"),
        help_text=_(
            "Choose a file (.csv, .yml, .yaml, .json). After Check or Import "
            "you must re-select the file - browsers never let a page prefill "
            "a file input - every other field below keeps the value you set."
        ),
    )

    # --- common options ---
    pipeline = forms.ChoiceField(
        required=False,
        label=_("Pipeline (optional)"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )
    page = forms.IntegerField(
        required=False,
        min_value=1,
        label=_("Page"),
        widget=forms.NumberInput(attrs={"class": "form-control"}),
    )
    size = forms.IntegerField(
        required=False,
        min_value=1,
        label=_("Size"),
        widget=forms.NumberInput(attrs={"class": "form-control"}),
    )

    # --- CSV-specific options (ignored server-side for non-.csv uploads) ---
    encoding = forms.ChoiceField(
        choices=[(e, e) for e in settings.SUPPORTED_ENCODING],
        required=False,
        initial="utf-8",
        label=_("Encoding"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )
    separator = forms.ChoiceField(
        choices=CSV_SEPARATOR_CHOICES,
        required=False,
        initial=",",
        label=_("Delimiter"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )
    split_multivalue = forms.BooleanField(
        required=False,
        initial=True,
        label=_("Split multi-value fields (^)"),
        widget=forms.CheckboxInput(attrs={"class": "form-check-input"}),
    )

    # --- advanced (p_data_admin only - see __init__) ---
    force_action = forms.ChoiceField(
        required=False,
        label=_("Force action"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )
    force_schema = forms.ChoiceField(
        required=False,
        label=_("Force schema"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )
    sync_mode = forms.BooleanField(
        required=False,
        initial=False,
        label=_("Touch last_sync"),
        help_text=_(
            "Update last_sync on every written object, same as ?sync=true on /api/load/ and /api/rawfile/."
        ),  # noqa: E501
        widget=forms.CheckboxInput(attrs={"class": "form-check-input"}),
    )

    def __init__(self, *args, pipelines=None, schemas=None, is_admin=False, **kwargs):
        """pipelines/schemas: Instance/Schema objects from the view (schemas
        already permission-filtered). is_admin: gates whether force_action/
        force_schema/sync_mode are even declared on this form instance."""

        super().__init__(*args, **kwargs)
        self.fields["pipeline"].choices = [BLANK_CHOICE] + [
            (p.keyname, p.displayname) for p in (pipelines or [])
        ]
        if is_admin:
            self.fields["force_action"].choices = [BLANK_CHOICE] + [
                (a, a) for a in settings.ACTION_LIST
            ]
            self.fields["force_schema"].choices = [BLANK_CHOICE] + [
                (s.classname, s.displayname) for s in (schemas or [])
            ]
        else:
            del self.fields["force_action"]
            del self.fields["force_schema"]
            del self.fields["sync_mode"]

    def clean(self):
        """page without size is rejected - mirrors the CLI's --page/--size
        convention ("--page requires --size"); there are no first/last
        inputs on the web form, so no mutual-exclusivity check is needed."""

        cleaned_data = super().clean()
        if cleaned_data.get("page") and not cleaned_data.get("size"):
            self.add_error("size", _("Size is required when Page is set"))
        return cleaned_data
