"""Helper functions for extracting values from request locations."""

from werkzeug.datastructures import Headers, MultiDict

from flask_jeroboam._utils import is_sequence_field
from flask_jeroboam.wrapper import current_app


def _extract_scalar(
    *,
    source: Headers | dict,
    name: str,
    alias: str,
    **_kwargs,
):
    """Extract a scalar value from a source."""
    return source.get(alias, source.get(name))


def _extract_sequence(
    *, source: MultiDict, name: str | None, alias: str | None, **_kwargs
) -> list:
    """Extract a Sequence value from a source."""
    _values = source.getlist(alias)
    if len(_values) == 0:
        _values = source.getlist(name)
    return _values


def _extract_sequence_with_key_transformer(
    *, source: MultiDict, name: str, alias: str, **_kwargs
):
    """Apply the key transformer to the source."""
    transformed_source = current_app.query_string_key_transformer(
        current_app, source.to_dict()
    )
    return _extract_scalar(source=transformed_source, name=name, alias=alias)


def _undirected_extraction(
    *,
    field,
    source,
    alias: str,
    name: str,
    has_key_transformer: bool,
    **_kwargs,
):
    if is_sequence_field(field):
        values = _extract_sequence(source=source, name=name, alias=alias)
        if len(values) == 0 and has_key_transformer:
            values = _extract_sequence_with_key_transformer(
                source=source, name=name, alias=alias
            )
    else:
        values = _extract_scalar(source=source, name=name, alias=alias)
    return values


def _extract_subfields(
    *,
    source: MultiDict,
    fields: dict,
    **_kwargs,
) -> dict:
    """Extract a Sequence from subfields."""
    has_key_transformer = (
        getattr(current_app, "query_string_key_transformer", False) is not None
    )
    result = {}
    for field_name, subfield in fields.items():
        value = _undirected_extraction(
            field=subfield,
            source=source,
            name=field_name,
            alias=subfield.alias,
            has_key_transformer=has_key_transformer,
        )
        if value is not None:
            result[field_name] = value
    return result
