from __future__ import annotations

from typing import Any, Dict, Tuple

from common.shared import (
    FLAVOR_ID,
    FLAVOR_MODE_LOWEST,
    FLAVOR_MODE_WAWACLOUD_20,
    FLAVOR_MODE_WAWACLOUD_LOW,
    LOW_CONFIG_FLAVORS_BY_REGION,
    LOW_CONFIG_RAM_MB,
    LOW_CONFIG_VCPUS,
    TARGET_RAM_MB,
    TARGET_VCPUS,
    TWENTY_CONFIG_FLAVORS,
)


def int_or_zero(value: Any) -> int:
    """把云接口返回的规格数字转成整数，异常时按 0 处理。"""
    try:
        return int(value)
    except Exception:
        return 0


def flavor_identity(flavor: Dict[str, Any]) -> str:
    """读取华为云规格的稳定标识，优先使用 id。"""
    return str(flavor.get("id") or flavor.get("name") or "")


def flavor_matches_target_size(flavor: Dict[str, Any]) -> bool:
    """判断规格是否符合默认 2C2G 目标。"""
    return int_or_zero(flavor.get("vcpus")) == TARGET_VCPUS and int_or_zero(flavor.get("ram")) == TARGET_RAM_MB


def flavor_matches_low_config_size(flavor: Dict[str, Any]) -> bool:
    """判断规格是否符合低配 1C1G 目标。"""
    return int_or_zero(flavor.get("vcpus")) == LOW_CONFIG_VCPUS and int_or_zero(flavor.get("ram")) == LOW_CONFIG_RAM_MB


def flavor_size(flavor: Dict[str, Any]) -> Tuple[int, int]:
    """返回规格的 vCPU 和内存大小。"""
    return int_or_zero(flavor.get("vcpus")), int_or_zero(flavor.get("ram"))


def flavor_has_usable_size(flavor: Dict[str, Any]) -> bool:
    """判断规格是否有有效的 CPU/内存数值。"""
    vcpus, ram = flavor_size(flavor)
    return vcpus > 0 and ram > 0


def flavor_is_probably_available(flavor: Dict[str, Any]) -> bool:
    """根据规格状态字段粗略排除售罄、下线或不可用规格。"""
    status_text = " ".join(
        str(flavor.get(key) or "")
        for key in (
            "status",
            "az_status",
            "cond:operation:status",
            "availability",
            "sold_out",
            "sell_status",
        )
    ).lower()
    if any(token in status_text for token in ("sold", "abandon", "deleted", "offline", "unavailable")):
        return False
    return True


def flavor_lowest_score(flavor: Dict[str, Any]) -> Tuple[int, int, int, str]:
    """给最低配候选规格排序，优先 CPU/内存更小且常见族系的规格。"""
    vcpus, ram = flavor_size(flavor)
    flavor_id = flavor_identity(flavor)
    lowered = flavor_id.lower()
    family_penalty = 0 if lowered.startswith(("x1.", "s.", "s1.", "s2.", "s3.", "s6.", "s7.", "c.", "c1.", "c2.", "c3.", "c6.", "c7.")) else 20
    return vcpus, ram, family_penalty, flavor_id


def flavor_preference_score(flavor: Dict[str, Any]) -> Tuple[int, str]:
    """给默认 2C2G 候选规格打分，优先固定规格和常用族系。"""
    flavor_id = flavor_identity(flavor)
    lowered = flavor_id.lower()
    score = 0
    if flavor_id == FLAVOR_ID:
        score += 1000
    if flavor_matches_target_size(flavor):
        score += 500
    if lowered.startswith("x1."):
        score += 80
    if lowered.startswith(("s7.", "s6.", "s3.", "c7.", "c6.")):
        score += 40
    if not flavor_is_probably_available(flavor):
        score -= 300
    return score, flavor_id


def flavor_mode_label(flavor_mode: str) -> str:
    """把规格模式转换成界面和日志里展示的中文说明。"""
    if flavor_mode == FLAVOR_MODE_WAWACLOUD_LOW:
        return "1vCPUs | 1GiB，按地区固定选择 s7.small.1 / x1.1u.1g"
    if flavor_mode == FLAVOR_MODE_WAWACLOUD_20:
        return f"20条IP，1vCPUs | 1GiB | {' / '.join(TWENTY_CONFIG_FLAVORS)}，2弹性网卡+2虚拟IP+16辅助弹性网卡"
    if flavor_mode == FLAVOR_MODE_LOWEST:
        return "最低配（按规格列表选择 vCPU/内存最小的可用规格）"
    return "2vCPUs | 2GiB，规格 x1.2u.2g"


def low_config_flavor_ids(region: str) -> Tuple[str, ...]:
    """按地区返回低配模式的优先规格。"""
    return LOW_CONFIG_FLAVORS_BY_REGION.get(region, ("s7.small.1",))
