from __future__ import annotations

from typing import Any


PLUGIN_SNAPSHOT_BLOCKED_KEYS = {
    "product_group_area",
    "product_group_node",
    "area",
    "node",
}


def sanitize_plugin_snapshot(snapshot: dict[str, Any] | None) -> dict[str, Any]:
    snap = snapshot if isinstance(snapshot, dict) else {}
    return {key: value for key, value in snap.items() if key not in PLUGIN_SNAPSHOT_BLOCKED_KEYS}


def split_pipe_value(value: Any) -> tuple[str, str]:
    text = str(value or "").strip()
    if "|" not in text:
        return text, text
    raw, label = text.split("|", 1)
    return raw.strip(), label.strip()


def config_field_key(field: dict[str, Any]) -> str:
    key, _ = split_pipe_value(field.get("def"))
    return key


def config_field_label(field: dict[str, Any]) -> str:
    key, label = split_pipe_value(field.get("def"))
    return label or key


def normalize_upstream_value(value: Any) -> Any:
    if isinstance(value, str):
        raw, _ = split_pipe_value(value)
        return raw
    return value


def value_present(value: Any) -> bool:
    return value is not None and value != ""


def _set_param(
    params: dict[str, Any],
    labels: dict[str, str],
    sources: dict[str, str],
    key: str,
    label: str,
    value: Any,
    source: str,
) -> None:
    normalized = normalize_upstream_value(value)
    if not key or not value_present(normalized):
        return
    params[key] = normalized
    labels[key] = label or key
    sources[key] = source


def _instance_value(instance: Any, attr: str) -> Any:
    return getattr(instance, attr, None) if instance is not None else None


def build_upstream_param_context(instance: Any, snapshot: dict[str, Any] | None) -> dict[str, Any]:
    snap = snapshot if isinstance(snapshot, dict) else {}
    slider_values = snap.get("slider_values") if isinstance(snap.get("slider_values"), dict) else {}
    provision_config = snap.get("provision_config") if isinstance(snap.get("provision_config"), list) else []

    params: dict[str, Any] = {}
    labels: dict[str, str] = {}
    sources: dict[str, str] = {}
    fields: list[dict[str, Any]] = []

    for field in provision_config:
        if not isinstance(field, dict):
            continue
        key = config_field_key(field)
        if not key:
            continue
        label = config_field_label(field)
        field_type = str(field.get("type") or "fixed")
        raw_value: Any = None
        source = f"provision_config.{field_type}"

        if field_type == "fixed":
            raw_value = field.get("value")
        elif field_type in {"slider", "user_select"}:
            if key in slider_values:
                raw_value = slider_values.get(key)
                source = "slider_values"
            elif field_type == "slider":
                raw_value = field.get("value")
                if not value_present(raw_value):
                    raw_value = field.get("slider_min")
                    source = "provision_config.slider_min"
            else:
                raw_value = field.get("value")
        elif field_type == "input":
            if key in slider_values:
                raw_value = slider_values.get(key)
                source = "slider_values"
            elif key == "hostname":
                raw_value = _instance_value(instance, "hostname")
                source = "instance.hostname"
            else:
                raw_value = field.get("value")
        else:
            raw_value = field.get("value")

        normalized = normalize_upstream_value(raw_value)
        if value_present(normalized):
            _set_param(params, labels, sources, key, label, normalized, source)
        fields.append({
            "key": key,
            "label": label,
            "type": field_type,
            "value": normalized if value_present(normalized) else None,
            "raw_value": raw_value,
            "source": source,
        })

    os_image = _instance_value(instance, "os_image")
    if "os" not in params and value_present(os_image):
        os_value, os_label = split_pipe_value(os_image)
        _set_param(params, labels, sources, "os", os_label or "OS", os_value, "instance.os_image")

    instance_defaults = {
        "cpu": _instance_value(instance, "cpu"),
        "memory": _instance_value(instance, "memory"),
        "system_disk_size": _instance_value(instance, "system_disk_size"),
        "data_disk_size": _instance_value(instance, "data_disk_size"),
        "in_bw": _instance_value(instance, "in_bw"),
        "out_bw": _instance_value(instance, "out_bw"),
        "ip_num": _instance_value(instance, "ip_num"),
        "nat_acl_limit": _instance_value(instance, "nat_acl_limit"),
        "traffic_quota": _instance_value(instance, "traffic_quota"),
        "traffic_type": _instance_value(instance, "traffic_type"),
    }
    for key, value in instance_defaults.items():
        if key not in params and value_present(value):
            _set_param(params, labels, sources, key, key, value, f"instance.{key}")
    if "bw" not in params and value_present(_instance_value(instance, "out_bw")):
        _set_param(params, labels, sources, "bw", "bw", _instance_value(instance, "out_bw"), "instance.out_bw")

    return {
        "params": params,
        "labels": labels,
        "sources": sources,
        "fields": fields,
    }


def plugin_purchase_fields(snapshot: dict[str, Any] | None) -> dict[str, Any]:
    snap = snapshot if isinstance(snapshot, dict) else {}
    slider_values = snap.get("slider_values") if isinstance(snap.get("slider_values"), dict) else {}
    fields = slider_values.get("__plugin_fields") if isinstance(slider_values, dict) else {}
    return fields if isinstance(fields, dict) else {}
