"""
Unit tests for form_factory helper functions and _ENUM_OPTION_TYPES.
"""

from enum import Enum
from typing import Any, cast
from unittest.mock import MagicMock

import pytest
from fields_metadata import FieldMetadata
from wtforms import SelectField

from orama.enums import (
    GeoProjection,
    LineInterpolation,
    LinePlacement,
    LineSortOrder,
    SortOrder,
)
from orama.options import (
    GeoProjectionOption,
    LineInterpolationOption,
    LinePlacementOption,
    LineSortOrderOption,
    SortOrderOption,
)
from orama.strategies.bar import BarChartStrategy
from orama.web.form_factory import (
    _ENUM_OPTION_TYPES,
    OPT_PREFIX,
    _add_option_field,
    create_figure_form_class,
)


def test_enum_option_types_keys() -> None:
    expected = {SortOrderOption, LinePlacementOption, LineInterpolationOption, LineSortOrderOption, GeoProjectionOption}
    assert set(_ENUM_OPTION_TYPES.keys()) == expected


def test_enum_option_types_sort_order_has_coerce() -> None:
    _, extra = _ENUM_OPTION_TYPES[SortOrderOption]
    assert extra == {"coerce": int}


@pytest.mark.parametrize(
    "opt_type,enum_cls",
    [
        (SortOrderOption, SortOrder),
        (LinePlacementOption, LinePlacement),
        (LineInterpolationOption, LineInterpolation),
        (LineSortOrderOption, LineSortOrder),
        (GeoProjectionOption, GeoProjection),
    ],
)
def test_add_option_field_enum_produces_select_field(
    opt_type: type,
    enum_cls: type[Enum],
) -> None:
    option = opt_type(
        name="Test",
        description="Test option",
        map_to="test_field",
        default_value=list(enum_cls)[0],
    )
    opt_desc = option.describe()
    attrs: dict[str, Any] = {}
    _add_option_field(attrs, opt_desc)
    key = f"{OPT_PREFIX}test_field"
    assert key in attrs
    assert attrs[key].field_class is SelectField
    expected_values = [e.value for e in enum_cls]
    field_values = [choice[0] for choice in attrs[key].kwargs["choices"]]
    assert field_values == expected_values


def test_create_figure_form_class_bar_strategy() -> None:
    cat_meta = MagicMock(spec=FieldMetadata)
    cat_meta.categorical = True
    cat_meta.numeric = False
    cat_meta.derived = False
    cat_meta.effective_type = str
    cat_meta.extra = {}
    num_meta = MagicMock(spec=FieldMetadata)
    num_meta.categorical = False
    num_meta.numeric = True
    num_meta.derived = False
    num_meta.effective_type = float
    num_meta.extra = {}
    fields_metadata = cast(dict[str, FieldMetadata], {"category": cat_meta, "value": num_meta})
    form_cls = create_figure_form_class(BarChartStrategy, fields_metadata)
    from wtforms import Form

    assert issubclass(form_cls, Form)
    form_cls()
