"""
Utility Functions for Rich Choices

This module provides utility functions for working with rich choice objects.
"""

from typing import Any

from .base import ChoiceCategory, RichChoice
from .registry import registry


def validate_choice_value(value: str, choice_group: str, domain: str = "core", allow_deprecated: bool = False) -> bool:
    """
    Validate that a choice value is valid for a given choice group.

    Args:
        value: The choice value to validate
        choice_group: Name of the choice group in the registry
        domain: Domain namespace for the choice group
        allow_deprecated: Whether to allow deprecated choices

    Returns:
        True if valid, False otherwise
    """
    if not value:
        return True  # Allow empty values (handled by field's null/blank settings)

    choice = registry.get_choice(choice_group, value, domain)
    if choice is None:
        return False

    return not (choice.deprecated and not allow_deprecated)


def get_choice_display(value: str, choice_group: str, domain: str = "core") -> str:
    """
    Get the display label for a choice value.

    Args:
        value: The choice value
        choice_group: Name of the choice group in the registry
        domain: Domain namespace for the choice group

    Returns:
        Display label for the choice

    Raises:
        ValueError: If the choice value is not found in the registry
    """
    if not value:
        return ""

    choice = registry.get_choice(choice_group, value, domain)
    if choice:
        return choice.label
    else:
        raise ValueError(f"Choice value '{value}' not found in group '{choice_group}' for domain '{domain}'")


def create_status_choices(
    statuses: dict[str, dict[str, Any]], category: ChoiceCategory = ChoiceCategory.STATUS
) -> list[RichChoice]:
    """
    Create status choices with consistent color coding.

    Args:
        statuses: Dictionary mapping status value to config dict
        category: Choice category (defaults to STATUS)

    Returns:
        List of RichChoice objects for statuses
    """
    choices = []

    for value, config in statuses.items():
        metadata = config.get("metadata", {})

        # Add default status colors if not specified
        if "color" not in metadata:
            if "operating" in value.lower() or "active" in value.lower():
                metadata["color"] = "green"
            elif "closed" in value.lower() or "inactive" in value.lower():
                metadata["color"] = "red"
            elif "temp" in value.lower() or "pending" in value.lower():
                metadata["color"] = "yellow"
            elif "construction" in value.lower():
                metadata["color"] = "blue"
            else:
                metadata["color"] = "gray"

        choice = RichChoice(
            value=value,
            label=config["label"],
            description=config.get("description", ""),
            metadata=metadata,
            deprecated=config.get("deprecated", False),
            category=category,
        )
        choices.append(choice)

    return choices


def create_type_choices(
    types: dict[str, dict[str, Any]], category: ChoiceCategory = ChoiceCategory.TYPE
) -> list[RichChoice]:
    """
    Create type/classification choices.

    Args:
        types: Dictionary mapping type value to config dict
        category: Choice category (defaults to TYPE)

    Returns:
        List of RichChoice objects for types
    """
    choices = []

    for value, config in types.items():
        choice = RichChoice(
            value=value,
            label=config["label"],
            description=config.get("description", ""),
            metadata=config.get("metadata", {}),
            deprecated=config.get("deprecated", False),
            category=category,
        )
        choices.append(choice)

    return choices


def merge_choice_metadata(base_metadata: dict[str, Any], override_metadata: dict[str, Any]) -> dict[str, Any]:
    """
    Merge choice metadata dictionaries.

    Args:
        base_metadata: Base metadata dictionary
        override_metadata: Override metadata dictionary

    Returns:
        Merged metadata dictionary
    """
    merged = base_metadata.copy()
    merged.update(override_metadata)
    return merged


def filter_choices_by_category(choices: list[RichChoice], category: ChoiceCategory) -> list[RichChoice]:
    """
    Filter choices by category.

    Args:
        choices: List of RichChoice objects
        category: Category to filter by

    Returns:
        Filtered list of choices
    """
    return [choice for choice in choices if choice.category == category]


def sort_choices(choices: list[RichChoice], sort_by: str = "sort_order") -> list[RichChoice]:
    """
    Sort choices by specified criteria.

    Args:
        choices: List of RichChoice objects
        sort_by: Sort criteria ("sort_order", "label", "value")

    Returns:
        Sorted list of choices
    """
    if sort_by == "sort_order":
        return sorted(choices, key=lambda x: (x.sort_order, x.label))
    elif sort_by == "label":
        return sorted(choices, key=lambda x: x.label)
    elif sort_by == "value":
        return sorted(choices, key=lambda x: x.value)
    else:
        return choices


def get_choice_colors(choice_group: str, domain: str = "core") -> dict[str, str]:
    """
    Get a mapping of choice values to their colors.

    Args:
        choice_group: Name of the choice group in the registry
        domain: Domain namespace for the choice group

    Returns:
        Dictionary mapping choice values to colors
    """
    choices = registry.get_choices(choice_group, domain)
    return {choice.value: choice.color for choice in choices if choice.color}


def validate_choice_group_data(name: str, choices: list[RichChoice], domain: str = "core") -> list[str]:
    """
    Validate choice group data and return list of errors.

    Args:
        name: Choice group name
        choices: List of RichChoice objects
        domain: Domain namespace

    Returns:
        List of validation error messages
    """
    errors = []

    if not name:
        errors.append("Choice group name cannot be empty")

    if not choices:
        errors.append("Choice group must contain at least one choice")
        return errors

    # Check for duplicate values
    values = [choice.value for choice in choices]
    if len(values) != len(set(values)):
        duplicates = [v for v in values if values.count(v) > 1]
        errors.append(f"Duplicate choice values found: {', '.join(set(duplicates))}")

    # Validate individual choices
    for i, choice in enumerate(choices):
        try:
            # This will trigger __post_init__ validation
            RichChoice(
                value=choice.value,
                label=choice.label,
                description=choice.description,
                metadata=choice.metadata,
                deprecated=choice.deprecated,
                category=choice.category,
            )
        except ValueError as e:
            errors.append(f"Choice {i}: {str(e)}")

    return errors


def create_choice_from_config(config: dict[str, Any]) -> RichChoice:
    """
    Create a RichChoice from a configuration dictionary.

    Args:
        config: Configuration dictionary with choice data

    Returns:
        RichChoice object
    """
    return RichChoice(
        value=config["value"],
        label=config["label"],
        description=config.get("description", ""),
        metadata=config.get("metadata", {}),
        deprecated=config.get("deprecated", False),
        category=ChoiceCategory(config.get("category", "other")),
    )


def export_choices_to_dict(choice_group: str, domain: str = "core") -> dict[str, Any]:
    """
    Export a choice group to a dictionary format.

    Args:
        choice_group: Name of the choice group in the registry
        domain: Domain namespace for the choice group

    Returns:
        Dictionary representation of the choice group
    """
    group = registry.get(choice_group, domain)
    if not group:
        return {}

    return group.to_dict()
