import importlib
import inspect
import re

from nicegui import ui
from xplan_tools.util import (
    cast_geom_to_multi,
    cast_geom_to_single,
    get_geometry_type_from_wkt,
)

from xmas_app.settings import get_settings


async def get_model_for_select(
    model_select: ui.select,
    wkt: str | None = None,
    feature_regex: str | None = None,
    appschema: str = get_settings().appschema,
    appschema_version: str = get_settings().appschema_version,
) -> list[str]:
    """Populate a UI select element.

    Args:
        model_select: The ui.select input element that should be populated.
        wkt: The WKT string of the current feature geometry.
        feature_regex: A regex pattern to limit the number of models to select.
        appschema: The appschema, e.g. 'xplan'.
        appschema_version: The appschema version.
    """

    def filter_members(model: object):
        """Filters the models in the appschema according to the provided WKT geometry and the featuretype regex."""
        # Only dive into models that can be instantiated
        if (
            hasattr(model, "model_fields")
            and model.model_fields.get("id")
            and not model.abstract
        ):
            geom_types = model.get_geom_types()
            if wkt and (geom_types := model.get_geom_types()):
                # Test if the provided WKT is valid for the model and cast it to its single/multi variant otherwise
                if get_geometry_type_from_wkt(wkt) not in geom_types:
                    if not wkt.startswith("MULTI"):
                        geom = cast_geom_to_multi(wkt)
                    else:
                        geom = cast_geom_to_single(wkt)
                    if get_geometry_type_from_wkt(geom) not in geom_types:
                        return False
            if feature_regex:
                if not re.match(feature_regex, model.get_name()):
                    return False
            return True

    options = [
        model.get_name()
        for _, model in inspect.getmembers(
            importlib.import_module(
                f"xplan_tools.model.appschema.{appschema + appschema_version.replace('.', '')}"
            ),
            filter_members,
        )
    ]
    # update the input element options
    model_select.set_options(options)
    if len(options) == 1:
        model_select.set_value(options[0])
