import datetime
from typing import Literal

import msgspec

from csirtmu.self_service_backend.enums import NetboxQueryType


class Step(msgspec.Struct):
    id: int
    title: str
    description: str | None


class TextStep(Step, tag="TextStep", tag_field="kind"):
    text: str


class LinkStep(Step, tag="LinkStep", tag_field="kind"):
    link: str


class FormField(msgspec.Struct):
    label: str
    position: int


class TextInput(FormField, tag="TextInput", tag_field="kind"):
    value: str | None = None
    max_chars: int | None = None
    type: Literal["default", "password"] = "default"
    help: str | None = None
    autocomplete: str | None = None
    placeholder: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"
    icon: str | None = None


class Selectbox(FormField, tag="Selectbox", tag_field="kind"):
    options: list[str]
    index: int | None = None
    help: str | None = None
    placeholder: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"
    accept_new_options: bool = False


class Multiselect(FormField, tag="Multiselect", tag_field="kind"):
    options: list[str]
    default: list[str] | None = None
    help: str | None = None
    max_selections: int | None = None
    placeholder: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"
    accept_new_options: bool = False


class TextArea(FormField, tag="TextArea", tag_field="kind"):
    value: str | None = None
    height: int | None = None
    max_chars: int | None = None
    help: str | None = None
    placeholder: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class NumberInput(FormField):
    format: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"
    icon: str | None = None
    help: str | None = None


class NumberInputInt(NumberInput, tag="NumberInputInt", tag_field="kind"):
    min_value: int | None = None
    max_value: int | None = None
    value: int | None = None
    step: int | None = None
    placeholder: int | None = None


class NumberInputFloat(FormField, tag="NumberInputFloat", tag_field="kind"):
    min_value: float | None = None
    max_value: float | None = None
    value: float | None = None
    step: float | None = None
    format: str | None = None
    help: str | None = None
    placeholder: float | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"
    icon: str | None = None


class Checkbox(FormField, tag="Checkbox", tag_field="kind"):
    value: bool = False
    help: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class Radio(FormField, tag="Radio", tag_field="kind"):
    options: list[str]
    index: int | None = 0
    help: str | None = None
    horizontal: bool = False
    captions: list[str] | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class DateInput(FormField, tag="DateInput", tag_field="kind"):
    value: datetime.date | None = None
    min_value: datetime.date | None = None
    max_value: datetime.date | None = None
    help: str | None = None
    format: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class TimeInput(FormField, tag="TimeInput", tag_field="kind"):
    value: datetime.time | None = None
    help: str | None = None
    step: int | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class FileUpload(FormField, tag="FileUpload", tag_field="kind"):
    type: list[str] | None = None
    accept_multiple_files: bool = False
    help: str | None = None
    label_visibility: Literal["visible", "hidden", "collapsed"] = "visible"


class TextField(FormField, tag="TextField", tag_field="kind"):
    text: str


class CompositeFormField(FormField, tag="CompositeFormField", tag_field="kind"):
    pass


class OneRequired(CompositeFormField, tag="OneRequired", tag_field="kind"):
    fields: list[Checkbox]


class OnSelection(CompositeFormField, tag="OnSelection", tag_field="kind"):
    selection_field: Radio | Selectbox
    mapping: dict[
        str,
        list[
            TextInput
            | Selectbox
            | Multiselect
            | TextArea
            | NumberInputInt
            | NumberInputFloat
            | Checkbox
            | Radio
            | DateInput
            | TimeInput
            | FileUpload
            | TextField
        ],
    ]


class DynamicSection(CompositeFormField, tag="DynamicSection", tag_field="kind"):
    fields: list[
        TextInput
        | Selectbox
        | Multiselect
        | TextArea
        | NumberInputInt
        | NumberInputFloat
        | Checkbox
        | Radio
        | DateInput
        | TimeInput
        | FileUpload
        | TextField
    ]
    default_amount: int


class FormStep(Step, tag="FormStep", tag_field="kind"):
    fields: list[
        TextInput
        | Selectbox
        | Multiselect
        | TextArea
        | NumberInputInt
        | NumberInputFloat
        | Checkbox
        | Radio
        | DateInput
        | TimeInput
        | FileUpload
        | TextField
        | OneRequired
        | OnSelection
        | DynamicSection
    ]
    clear_on_submit: bool = False
    border: bool = True


class NetboxSearchStep(Step, tag="NetboxSearchStep", tag_field="kind"):
    query_type: NetboxQueryType


class OutlineSearchStep(Step, tag="OutlineSearchStep", tag_field="kind"): ...
