from copy import deepcopy
from typing import Any
import re


def to_int_or_none(value: Any) -> int | None:
    if value in (None, ""):
        return None
    if isinstance(value, str):
        value = value.split("|", 1)[0].strip()
    try:
        return int(float(value))
    except (TypeError, ValueError):
        return None


def parse_memory_to_mb(value: Any) -> int | None:
    if value in (None, ""):
        return None
    if isinstance(value, (int, float)):
        return int(value)

    raw = str(value).strip()
    if not raw:
        return None

    normalized = raw.replace(" ", "").lower()
    match = re.match(r"^(\d+(?:\.\d+)?)(g|gb|m|mb)?$", normalized)
    if not match:
        return to_int_or_none(raw)

    amount = float(match.group(1))
    unit = match.group(2) or "mb"
    if unit in {"g", "gb"}:
        return int(amount * 1024)
    return int(amount)


def sync_provision_config_specs(
    provision_config: list[Any] | None,
    *,
    vcpu: int | None,
    memory: str | None,
) -> list[Any] | None:
    if not isinstance(provision_config, list):
        return provision_config

    config = deepcopy(provision_config)
    if vcpu is not None:
        _upsert_fixed_config(config, "cpu", "CPU核心数", str(vcpu))

    memory_mb = parse_memory_to_mb(memory)
    if memory_mb is not None:
        _upsert_fixed_config(config, "memory", "内存(MB)", str(memory_mb))

    return config


def _upsert_fixed_config(config: list[Any], key: str, label: str, value: str) -> None:
    for field in config:
        if not isinstance(field, dict):
            continue
        field_key = str(field.get("def", "")).split("|", 1)[0].strip()
        if field_key == key:
            field["def"] = field.get("def") or f"{key}|{label}"
            field["type"] = "fixed"
            field["value"] = value
            return

    config.append({"def": f"{key}|{label}", "type": "fixed", "value": value})
