"""
Color-building helpers for the orama web layer.

These functions translate WTForms ColorRuleForm subform data into domain-level
ColorRule objects.
"""

from typing import Any

from polychromos.color import HSLColor

from orama.color import (
    ColorAssignerByCategory,
    ColorAssignerByGroup,
    ColorAssignerByValue,
    ColorAssignerStrategy,
    ColorRule,
    ColorSelectByCategoryName,
    ColorSelectMaxValue,
    ColorSelectMinValue,
    ColorSelectorStrategy,
    ColorSelectValuesAbove,
    ColorSelectValuesAboveMean,
    ColorSelectValuesBelow,
    ColorSelectValuesBelowMean,
)
from orama.theme import Theme


def _make_anchor_colors(subform: Any, theme: Theme) -> list[HSLColor]:
    """
    Resolve anchor colors from a ColorRuleForm subform entry.

    :param subform: A FormField(ColorRuleForm) entry from the FieldList.
    :param theme: The theme used to resolve color names and hex values.
    :return: A non-empty list of HSLColor values.
    :rtype: list[HSLColor]
    """
    anchor_colors: list[HSLColor] = []
    for ac_entry in subform.anchor_colors:
        name = (ac_entry.form.name.data or "").strip()
        hex_val = (ac_entry.hex.data or "").strip()
        if name:
            try:
                anchor_colors.append(theme.get_color(name))
            except (ValueError, KeyError):
                pass
        elif hex_val:
            try:
                anchor_colors.append(HSLColor.from_hex(hex_val))
            except (ValueError, TypeError):
                pass
    return anchor_colors if anchor_colors else theme.get_default_color_sequence()


def _make_selector(selector_type: str, subform: Any) -> ColorSelectorStrategy:
    """
    Build a ColorSelectorStrategy from the form subform data.

    :param selector_type: String type identifier (e.g. ``"ValuesBelow"``).
    :param subform: The ColorRuleForm-backed FormField entry.
    :return: A configured ColorSelectorStrategy.
    :rtype: ColorSelectorStrategy
    """
    if selector_type == "ByCategoryName":
        raw = (subform.selector_category.data or "").strip()
        names = [c.strip() for c in raw.split(",") if c.strip()]
        return ColorSelectByCategoryName(names=names)
    if selector_type == "ValuesBelow":
        threshold = subform.selector_threshold.data
        if threshold is None:
            return ColorSelectorStrategy()
        return ColorSelectValuesBelow(threshold=threshold)
    if selector_type == "ValuesAbove":
        threshold = subform.selector_threshold.data
        if threshold is None:
            return ColorSelectorStrategy()
        return ColorSelectValuesAbove(threshold=threshold)
    if selector_type == "MinValue":
        return ColorSelectMinValue()
    if selector_type == "MaxValue":
        return ColorSelectMaxValue()
    if selector_type == "ValuesBelowMean":
        return ColorSelectValuesBelowMean()
    if selector_type == "ValuesAboveMean":
        return ColorSelectValuesAboveMean()
    return ColorSelectorStrategy()


def _make_assigner(assigner_type: str, subform: Any, theme: Theme) -> ColorAssignerStrategy:
    """
    Build a ColorAssignerStrategy from the form subform data.

    :param assigner_type: String type identifier (e.g. ``"ByValue"``).
    :param subform: The ColorRuleForm-backed FormField entry.
    :param theme: The theme used to resolve anchor colors.
    :return: A configured ColorAssignerStrategy.
    :rtype: ColorAssignerStrategy
    """
    anchor_colors = _make_anchor_colors(subform, theme)
    if assigner_type == "ByGroup":
        return ColorAssignerByGroup(anchor_colors=anchor_colors)
    if assigner_type == "ByValue":
        return ColorAssignerByValue(
            anchor_colors=anchor_colors,
            range_min=subform.assigner_range_min.data,
            range_max=subform.assigner_range_max.data,
            range_center_at=subform.assigner_range_center.data,
        )
    return ColorAssignerByCategory(anchor_colors=anchor_colors)


def _color_rule_from_subform(subform: Any, theme: Theme) -> ColorRule:
    """
    Build a ColorRule from a ColorRuleForm subform entry.

    :param subform: A FormField(ColorRuleForm) entry from the color_rules FieldList.
    :param theme: The theme used to resolve colors.
    :return: A configured ColorRule.
    :rtype: ColorRule
    """
    selector_type = (subform.selector_type.data or "All").strip()
    assigner_type = (subform.assigner_type.data or "ByCategory").strip()
    selector = _make_selector(selector_type, subform)
    assigner = _make_assigner(assigner_type, subform, theme)
    return ColorRule(selector=selector, assigner=assigner)
