# -*- coding: utf-8 -*-  # 指定文件编码为 UTF-8，确保中文注释不乱码。 
import decimal  # 导入 decimal 用于精确处理金额字符串。 
import os  # 导入 os 用于读取环境变量中的 AK/SK。 
from typing import Dict, Tuple, Optional  # 导入类型标注工具便于阅读与提示。 
import volcenginesdkcore  # 导入火山引擎 SDK Core 以配置 AK/SK。 
import volcenginesdkbilling  # 导入火山引擎 Billing SDK 调用余额接口。 
from volcenginesdkcore.rest import ApiException  # 导入 SDK 异常类型用于捕获接口错误。 
try:
    from volcengine import config  # 购买子进程使用顶层包路径。
except ImportError:
    from . import config  # 主界面直接导入 Volcengine.api 时使用相对路径。

def _normalize(value: Optional[str]) -> str:  # 统一处理字符串输入，避免空值异常。 
    return (value or "").strip()  # 返回去除空格后的字符串。 

def _build_configuration(ak: str, sk: str, region: str) -> volcenginesdkcore.Configuration:  # 构建 SDK 配置对象。 
    configuration = volcenginesdkcore.Configuration()  # 创建 SDK 配置实例。 
    configuration.ak = ak  # 设置 Access Key。 
    configuration.sk = sk  # 设置 Secret Key。 
    configuration.region = region  # 设置请求地域。 
    return configuration  # 返回配置对象供调用方使用。 

def _to_dict(obj) -> Dict:  # 将 SDK 返回对象安全转换为字典。 
    if obj is None:  # 判断对象是否为空。 
        return {}  # 为空时返回空字典。 
    if isinstance(obj, dict):  # 如果已经是字典直接返回。 
        return obj  # 返回字典本身。 
    to_dict = getattr(obj, "to_dict", None)  # 尝试读取对象的 to_dict 方法。 
    if callable(to_dict):  # 如果 to_dict 可调用则执行转换。 
        return to_dict()  # 返回转换后的字典。 
    result = getattr(obj, "result", None)  # 尝试读取常见的 result 属性。 
    if isinstance(result, dict):  # 如果 result 是字典则直接返回。 
        return result  # 返回 result 字典。 
    return {}  # 默认返回空字典避免崩溃。 

def _resolve_credentials(ak: Optional[str], sk: Optional[str]) -> Tuple[str, str]:  # 统一解析 AK/SK 来源。 
    ak_value = _normalize(ak)  # 清理传入 AK 的空格。 
    sk_value = _normalize(sk)  # 清理传入 SK 的空格。 
    if ak_value and sk_value:  # 若调用方已传入 AK/SK 则直接使用。 
        return ak_value, sk_value  # 返回传入的 AK/SK。 
    env_ak = _normalize(os.getenv("VOLC_AK"))  # 尝试从环境变量读取 AK。 
    env_sk = _normalize(os.getenv("VOLC_SK"))  # 尝试从环境变量读取 SK。 
    if env_ak and env_sk:  # 若环境变量存在则使用。 
        return env_ak, env_sk  # 返回环境变量中的 AK/SK。 
    cfg_ak = _normalize(getattr(config, "DEFAULT_ACCESS_KEY", ""))  # 读取配置文件中的默认 AK。 
    cfg_sk = _normalize(getattr(config, "DEFAULT_SECRET_KEY", ""))  # 读取配置文件中的默认 SK。 
    return cfg_ak, cfg_sk  # 返回配置文件中的默认 AK/SK（可能为空）。 

def _pick_region_from_env() -> str:  # 从环境变量中解析地域（优先网页传参）。 
    env_counts = _normalize(os.getenv("VOLC_REGION_COUNTS"))  # 读取 region=count 形式配置。 
    if env_counts:  # 若配置存在则取第一个地域。 
        for raw in env_counts.split(","):  # 逐段解析。 
            item = raw.strip()  # 清理空格。 
            if not item:  # 跳过空项。 
                continue 
            region_value = item.split("=", 1)[0]  # 只取 region 部分。 
            region_value = _normalize(region_value)  # 清理地域。 
            if region_value:  # 找到有效地域即返回。 
                return region_value 
    env_regions = _normalize(os.getenv("VOLC_REGIONS"))  # 读取地域列表配置。 
    if env_regions:  # 若配置存在则取第一个地域。 
        for raw in env_regions.split(","): 
            region_value = _normalize(raw) 
            if region_value: 
                return region_value 
    return ""  # 未从环境变量中解析到地域。 


def _resolve_region(region: Optional[str]) -> str:  # 统一解析地域参数。 
    region_value = _normalize(region)  # 清理传入 region 的空格。 
    if region_value:  # 若调用方传入 region 则使用。 
        return region_value  # 返回传入 region。 
    env_region = _pick_region_from_env()  # 优先尝试环境变量。 
    if env_region:  # 若环境变量有值则使用。 
        return env_region  # 返回环境变量地域。 
    for key in ("DEFAULT_REGION", "BJ", "SH", "GZ"):  # 依次尝试配置默认地域与常用地域常量。 
        fallback = _normalize(getattr(config, key, "")) 
        if fallback: 
            return fallback  # 返回配置中的地域。 
    return ""  # 全部为空时返回空字符串。 

def query_balance(ak: Optional[str], sk: Optional[str], region: Optional[str]) -> Tuple[bool, str, Dict]:  # 查询账户余额接口。 
    ak_value, sk_value = _resolve_credentials(ak, sk)  # 解析 AK/SK 的最终来源。 
    region_value = _resolve_region(region)  # 解析 region 的最终来源。 
    if not ak_value or not sk_value:  # 若 AK/SK 为空则返回失败。 
        return False, "AK/SK 为空，请通过网页传入或在 config.py 配置", {}  # 返回缺失提示。 
    if not region_value:  # 若 region 为空则返回失败。 
        return False, "地域为空，请通过网页传入或在 config.py 配置", {}  # 返回缺失提示。 
    configuration = _build_configuration(ak_value, sk_value, region_value)  # 构建请求配置。 
    volcenginesdkcore.Configuration.set_default(configuration)  # 设置 SDK 默认配置供后续调用使用。 
    api_instance = volcenginesdkbilling.BILLINGApi()  # 创建 Billing API 实例。 
    request = volcenginesdkbilling.QueryBalanceAcctRequest()  # 构建余额查询请求对象。 
    try:  # 捕获 SDK 调用异常。 
        response = api_instance.query_balance_acct(request)  # 调用余额查询接口。 
    except ApiException as exc:  # 捕获火山 SDK 抛出的异常。 
        return False, f"余额查询失败: {exc}", {}  # 返回失败状态与错误信息。 
    except Exception as exc:  # 网络层或 SDK 运行时异常也必须转成可提示的失败结果。
        return False, f"余额查询失败: {exc}", {}
    data = _to_dict(response)  # 将响应对象转换为字典。 
    result = data.get("Result") or data.get("result") or data  # 兼容不同响应结构。 
    return True, "余额查询成功", result  # 返回成功状态与结果。 

def get_available_balance(ak: Optional[str], sk: Optional[str], region: Optional[str]) -> Tuple[bool, str, Optional[decimal.Decimal]]:  # 解析可用余额。 
    ok, message, result = query_balance(ak, sk, region)  # 调用余额查询获取结果。 
    if not ok:  # 若查询失败直接返回。 
        return False, message, None  # 返回失败信息与空余额。 
    balance_value = result.get("AvailableBalance") or result.get("available_balance")  # 获取可用余额字段。 
    if balance_value is None:  # 若字段不存在则返回失败。 
        return False, "余额字段缺失", None  # 返回缺失提示。 
    try:  # 捕获余额解析异常。 
        balance = decimal.Decimal(str(balance_value))  # 将余额转换为 Decimal。 
    except (decimal.InvalidOperation, ValueError):  # 捕获转换错误。 
        return False, "余额解析失败", None  # 返回解析失败提示。 
    return True, "余额解析成功", balance  # 返回成功状态与余额数值。 
