from huaweicloudsdkcore.auth.credentials import BasicCredentials  # 导入华为云 SDK 的基础鉴权对象。 
from huaweicloudsdkcore.region.region import Region  # 导入区域对象用于设置服务端点。 
from huaweicloudsdkvpc.v2 import VpcClient, CreateVpcRequest, ListVpcsRequest  # 导入 VPC 客户端与创建/查询请求模型。 
from config import PROJECT_ID, get_runtime_ak_sk  # 导入鉴权参数用于构造客户端。 
from iam_service import get_project_id  # 导入自动获取项目 ID 的函数。 
from data import VPC_NAME, VPC_DESCRIPTION, VPC_CIDR, VPC_AUTO_REUSE, runtime_resource_name  # 导入 VPC 名称、描述、网段与复用配置。 
from data import VPC_ENTERPRISE_PROJECT_ID, VPC_TAGS  # 导入企业项目与标签配置。
from data import VPC_BLOCK_SERVICE_ENDPOINT_STATES, VPC_ENABLE_NETWORK_ADDRESS_USAGE_METRICS  # 导入 VPC 可选控制项。
from data import VPC_ENDPOINT_TEMPLATE  # 导入 VPC 服务端点模板用于拼接请求地址。
from retry_utils import is_transient_cloud_error, retry_cloud_call  # 导入华为云临时网络异常重试工具。
def _build_vpc_body(vpc_name):  # 组装 VPC 请求体的函数。 
    vpc_body = {  # 创建 VPC 请求体字典。 
        "name": vpc_name,  # VPC 名称字段。 
        "description": VPC_DESCRIPTION,  # VPC 描述字段。 
        "cidr": VPC_CIDR,  # VPC 网段字段。 
        "enterprise_project_id": VPC_ENTERPRISE_PROJECT_ID,  # 企业项目 ID 字段。 
        "tags": VPC_TAGS,  # VPC 标签字段。 
        "block_service_endpoint_states": VPC_BLOCK_SERVICE_ENDPOINT_STATES,  # 是否禁用内网服务终结点字段。 
        "enable_network_address_usage_metrics": VPC_ENABLE_NETWORK_ADDRESS_USAGE_METRICS,  # 是否启用地址使用率监控字段。 
    }  # VPC 请求体初始字典定义结束。 
    filtered_body = {k: v for k, v in vpc_body.items() if v not in (None, "", [], {})}  # 过滤空值字段避免接口报错。 
    return filtered_body  # 返回过滤后的请求体字典。 
def _resolve_project_id(region_id):  # 根据配置或 IAM 自动解析项目 ID。 
    if PROJECT_ID and PROJECT_ID != "YOUR_PROJECT_ID":  # 若已手工配置项目 ID 则直接使用。 
        return PROJECT_ID  # 返回手工配置的项目 ID。 
    return get_project_id(region_id)  # 否则调用 IAM 接口自动获取项目 ID。 
def _build_vpc_client(region_id):  # 创建 VPC 客户端的函数。 
    project_id = _resolve_project_id(region_id)  # 获取当前区域对应的项目 ID。 
    ak, sk = get_runtime_ak_sk()  # 读取当前线程生效的 AK/SK。 
    creds = BasicCredentials(ak, sk).with_project_id(project_id)  # 使用 AK/SK 与项目 ID 构造鉴权对象。 
    endpoint = VPC_ENDPOINT_TEMPLATE.format(region_id=region_id)  # 根据区域拼接 VPC 服务端点。 
    region = Region(region_id, endpoint)  # 创建区域对象并绑定端点。 
    client = VpcClient.new_builder().with_credentials(creds).with_region(region).build()  # 构建 VPC 客户端实例。 
    return client  # 返回构建好的客户端对象。 
def _find_vpc_by_name(region_id, vpc_name):  # 按名称查找 VPC 的函数。 
    if not vpc_name:  # 若未提供名称则无法判断是否复用。 
        return None  # 直接返回空值表示不复用。 
    client = _build_vpc_client(region_id)  # 构建 VPC 客户端用于查询。 
    request = ListVpcsRequest()  # 创建查询 VPC 列表的请求对象。 
    response = retry_cloud_call("查询VPC列表", lambda: client.list_vpcs(request))  # 调用 SDK 查询 VPC 列表。
    for vpc in response.vpcs or []:  # 遍历 VPC 列表尝试匹配名称。 
        if vpc.name == vpc_name:  # 若名称匹配则认为可复用。 
            return vpc.id  # 返回匹配到的 VPC ID。 
    return None  # 未找到匹配项则返回空值。 
def create_vpc(region_id):  # 创建 VPC 的函数实现。 
    vpc_name = runtime_resource_name(VPC_NAME)  # 多套资源按编号使用独立 VPC。
    if VPC_AUTO_REUSE:  # 若开启复用则优先查找同名 VPC。 
        existed_id = _find_vpc_by_name(region_id, vpc_name)  # 按名称查找是否已有 VPC。 
        if existed_id:  # 若找到则直接返回现有 VPC ID。 
            return existed_id  # 复用现有 VPC 避免重复创建。 
    client = _build_vpc_client(region_id)  # 构建 VPC 客户端以调用创建接口。 
    vpc_body = _build_vpc_body(vpc_name)  # 构建 VPC 请求体。 
    request = CreateVpcRequest()  # 创建 VPC 请求对象。 
    request.body = {"vpc": vpc_body}  # 填充请求体以符合 API 结构要求。 
    # 创建类接口如果响应丢失，可能云上已经创建成功；重试前先按名称反查，避免重复下单。
    for attempt in range(1, 4):
        try:
            response = retry_cloud_call("创建VPC", lambda: client.create_vpc(request), attempts=1)
            return response.vpc.id  # 返回新建 VPC 的 ID。
        except Exception as exc:
            if not is_transient_cloud_error(exc) or attempt >= 3:
                raise
            existed_id = _find_vpc_by_name(region_id, vpc_name)
            if existed_id:
                return existed_id
            print(f"步骤: 创建VPC临时异常，重试 {attempt + 1}/3: {exc}")
    raise RuntimeError("创建VPC失败")
