from pathlib import Path

from django import forms

from apps.scenarios.services import ScenarioNotFound, get_scenario
from apps.scenarios.services import list_scenarios

SUPPORTED_EXTENSIONS = {".txt", ".md", ".pdf", ".docx", ".zip", ".7z", ".rar"}


class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True


class MultipleFileField(forms.FileField):
    widget = MultipleFileInput

    def clean(self, data, initial=None):
        single_file_clean = super().clean
        if not data:
            return []
        if isinstance(data, (list, tuple)):
            return [single_file_clean(item, initial) for item in data]
        return [single_file_clean(data, initial)]


class DocumentUploadForm(forms.Form):
    # 使用 ChoiceField 让表单自己维护场景选项，
    # 这样模板、校验和后续扩展都能围绕一个入口完成。
    scenario_id = forms.ChoiceField(label="场景", choices=())
    files = MultipleFileField(label="文件或资料包", required=False)
    file = forms.FileField(label="兼容单文件上传", required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["scenario_id"].choices = [
            (scenario["id"], scenario["name"])
            for scenario in list_scenarios()
        ]

    def clean_scenario_id(self):
        scenario_id = self.cleaned_data["scenario_id"]
        try:
            get_scenario(scenario_id)
        except ScenarioNotFound as exc:
            raise forms.ValidationError("场景不存在") from exc
        return scenario_id

    def clean_file(self):
        uploaded_file = self.cleaned_data["file"]
        if not uploaded_file:
            return uploaded_file
        extension = Path(uploaded_file.name).suffix.lower()
        if extension not in SUPPORTED_EXTENSIONS:
            raise forms.ValidationError("仅支持 .txt、.md、.pdf、.docx、.zip、.7z 和 .rar 文件")
        return uploaded_file

    def clean_files(self):
        uploaded_files = self.cleaned_data.get("files") or []
        for uploaded_file in uploaded_files:
            extension = Path(uploaded_file.name).suffix.lower()
            if extension not in SUPPORTED_EXTENSIONS:
                raise forms.ValidationError("仅支持 .txt、.md、.pdf、.docx、.zip、.7z 和 .rar 文件")
        return uploaded_files

    def clean(self):
        cleaned_data = super().clean()
        files = list(cleaned_data.get("files") or [])
        file = cleaned_data.get("file")
        if file:
            files.append(file)
        if not files:
            raise forms.ValidationError("请至少上传一个文件或一个 zip 资料包。")
        cleaned_data["uploaded_files"] = files
        return cleaned_data
