"""Schema builder - converts dict schemas to ParametersSchema.

Supports minimal forms (int, float) and full specifications.
"""

from __future__ import annotations

from typing import Any

from hil_testbench.data_structs.parameters import (
    ParametersSchema,
    ParameterField,
    Threshold,
)


def build_schema(schema_dict: dict[str, Any]) -> ParametersSchema:
    """Build ParametersSchema from dictionary specification.

    Supports two forms:

    Minimal form (just type):
        {"count": int, "temp": float}

    Full form (with metadata):
        {
            "cpu_temp": {
                "type": float,
                "unit": "°C",
                "description": "CPU temperature",
                "thresholds": {"good": (0, 65), "warn": (65, 80), "bad": (80, 100)},
            }
        }

    Args:
        schema_dict: Dictionary mapping field names to type or spec dict

    Returns:
        ParametersSchema instance
    """
    fields = []

    for name, spec in schema_dict.items():
        if isinstance(spec, type):
            # Minimal form: {"count": int}
            fields.append(ParameterField(name=name, type=spec))
        elif isinstance(spec, dict):
            # Full form: extract all properties
            field_type = spec.get("type")
            if not field_type:
                raise ValueError(f"Schema field '{name}' must have 'type' property")

            # Build thresholds if provided
            thresholds = {}
            if "thresholds" in spec:
                thresholds_dict = spec["thresholds"]
                for threshold_name, threshold_spec in thresholds_dict.items():
                    # Handle nested dict format: {"value": ..., "operator": ..., "color": ...}
                    if isinstance(threshold_spec, dict):
                        raw_value = threshold_spec.get("value")
                        if isinstance(raw_value, (list, tuple)) and len(raw_value) == 2:
                            value = (float(raw_value[0]), float(raw_value[1]))
                            default_mode = "range"
                        elif isinstance(raw_value, (int, float)):
                            value = float(raw_value)
                            default_mode = "gt"
                        else:
                            value = 0.0
                            default_mode = "gt"
                        mode = threshold_spec.get("operator", default_mode)
                        color = threshold_spec.get(
                            "color", _get_threshold_color(threshold_name)
                        )
                        thresholds[threshold_name] = Threshold(value, mode, color)
                    # Handle simple tuple/value format
                    elif isinstance(threshold_spec, tuple):
                        # Range: (min, max)
                        value = (
                            (float(threshold_spec[0]), float(threshold_spec[1]))
                            if len(threshold_spec) == 2
                            else (0.0, 0.0)
                        )
                        thresholds[threshold_name] = Threshold(
                            value,
                            "range",
                            color=_get_threshold_color(threshold_name),
                        )
                    else:
                        # Single value
                        value = (
                            float(threshold_spec)
                            if isinstance(threshold_spec, (int, float))
                            else 0.0
                        )
                        thresholds[threshold_name] = Threshold(
                            value,
                            "gt",
                            color=_get_threshold_color(threshold_name),
                        )

            fields.append(
                ParameterField(
                    name=name,
                    type=field_type,
                    unit=spec.get("unit", ""),
                    description=spec.get("description", ""),
                    thresholds=thresholds,
                    precision=int(spec.get("precision", 2)),
                    scale_strategy=spec.get("scale_strategy", "raw"),
                    display_enabled=spec.get("display_enabled", True),
                )
            )
        else:
            raise ValueError(
                f"Schema field '{name}' must be a type or dict, got {type(spec)}"
            )

    return ParametersSchema(fields=fields)


def _get_threshold_color(threshold_name: str) -> str:
    """Get default color for threshold name."""
    threshold_colors = {
        "good": "green",
        "warn": "yellow",
        "warning": "yellow",
        "bad": "red",
        "error": "red",
        "critical": "red",
    }
    return threshold_colors.get(threshold_name.lower(), "white")
