from typing import Any

from custom_components.powercalc.configuration.normalization import normalize_state_trigger
from custom_components.powercalc.const import (
    CONF_FIXED_VALUE,
    CONF_PLAYBOOK_ID,
    CONF_POWER,
    CONF_POWER_TEMPLATE,
    CONF_STATE,
    CONF_STATE_TRIGGER,
    CONF_STATES_POWER,
    CalculationStrategy,
)
from custom_components.powercalc.flow_helper.common import unwrap_choose_selector, wrap_choose_selector

FIXED_CHOICES: dict[str, list[str] | str] = {
    CONF_STATES_POWER: CONF_STATES_POWER,
    CONF_POWER_TEMPLATE: CONF_POWER_TEMPLATE,
    CONF_POWER: CONF_POWER,
}


def order_choices_for_default[T](
    choices: dict[str, T],
    default_choice: str | None,
) -> dict[str, T]:
    """Put the default choice first because HA initializes choose selectors from the first choice."""
    if default_choice not in choices:
        return choices
    return {
        default_choice: choices[default_choice],
        **{choice: config for choice, config in choices.items() if choice != default_choice},
    }


def has_saved_choice_value(value: object) -> bool:
    """Return whether a saved strategy value should drive the selected form choice."""
    if value is None:
        return False
    if isinstance(value, (str, list, dict)):
        return bool(value)
    return True


def find_present_choice(form_data: dict[str, Any], choices: dict[str, list[str] | str]) -> str | None:
    """Find the first choice that has matching config data."""
    for choice_id, mapping in choices.items():
        keys = [mapping] if isinstance(mapping, str) else mapping
        if any(has_saved_choice_value(form_data.get(key)) for key in keys):
            return choice_id
    return None


def fixed_choice_key_from_validated_value(value: object) -> str:
    """Infer the fixed strategy config key from a validated ChooseSelector value."""
    if isinstance(value, list):
        return CONF_STATES_POWER
    if isinstance(value, str):
        return CONF_POWER_TEMPLATE
    return CONF_POWER


def unwrap_strategy_user_input(strategy: CalculationStrategy, user_input: dict[str, Any]) -> dict[str, Any]:
    """Unwrap form-only selector wrappers and normalize strategy user input."""
    if strategy == CalculationStrategy.FIXED:
        unwrap_choose_selector(user_input, CONF_FIXED_VALUE, fixed_choice_key_from_validated_value)
    if CONF_STATE_TRIGGER in user_input:
        user_input[CONF_STATE_TRIGGER] = normalize_state_trigger(user_input[CONF_STATE_TRIGGER])
    return user_input


def wrap_strategy_form_data(strategy: CalculationStrategy, form_data: dict[str, Any]) -> dict[str, Any]:
    """Wrap stored strategy config back into form-only selector structures."""
    if strategy == CalculationStrategy.FIXED:
        choices = order_choices_for_default(FIXED_CHOICES, find_present_choice(form_data, FIXED_CHOICES))
        form_data = wrap_choose_selector(form_data, CONF_FIXED_VALUE, choices, raw_value=True)
    if CONF_STATE_TRIGGER in form_data and isinstance(form_data[CONF_STATE_TRIGGER], dict):
        form_data = {
            **form_data,
            CONF_STATE_TRIGGER: [
                {CONF_STATE: state, CONF_PLAYBOOK_ID: playbook_id}
                for state, playbook_id in form_data[CONF_STATE_TRIGGER].items()
            ],
        }
    return form_data
