"""Hezor2 SDK pull_configs 使用示例。

本示例演示通过 Hezor2 SDK 从配置中心拉取配置：

1. 拉取全量配置（public + user 分组展示）
2. 按 key 列表过滤，只拉取指定配置项
3. 自定义 global_base_url（反向代理 / 自定义域名场景）

Usage
-----
运行所有示例:
    uv run examples/transfer/hezor2_sdk/pull_configs_example.py

运行指定示例:
    uv run examples/transfer/hezor2_sdk/pull_configs_example.py 1
    uv run examples/transfer/hezor2_sdk/pull_configs_example.py 2
    uv run examples/transfer/hezor2_sdk/pull_configs_example.py 3

列出所有示例:
    uv run examples/transfer/hezor2_sdk/pull_configs_example.py --list
"""

import asyncio
import logging
import os
import sys
from pathlib import Path

from dotenv import load_dotenv

# ⚠️ 重要：必须在导入 SDK 之前加载环境变量
# 因为 constants.py 在模块导入时会读取环境变量创建默认值
env_file = Path(__file__).parent.parent.parent / ".env"
load_dotenv(dotenv_path=env_file)

sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))

from hezor_common.transfer.hezor2_sdk import Hezor2SDK, MetaInfo  # noqa: E402
from hezor_common.transfer.hezor2_sdk.env_config import Hezor2EnvConfig  # noqa: E402

logging.basicConfig(
    level=logging.WARNING,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)

print(f"✓ 已加载环境变量: {env_file}")
print()

config = Hezor2EnvConfig()
print(f"✓ API Base URL: {config.hezor2_api_base_url}")
print()


def _build_sdk() -> Hezor2SDK:
    """构建 SDK 实例（带可选的认证配置）。"""
    kwargs: dict = {
        "base_url": config.hezor2_api_base_url,
        "api_key": config.hezor2_api_key,
    }

    if config.hezor2_app_name:
        kwargs["app_name"] = config.hezor2_app_name

    kwargs["meta_info"] = MetaInfo(
        caller_id="example/pull_configs",
        subject="example",
        subject_code="example_001",
        creation_name="示例创建",
        creation_slug="example_creation",
        data_coverage="20240101-20241231",
    )

    if config.hezor2_header_pk_filepath:
        private_key_path = Path(config.hezor2_header_pk_filepath)
        if not private_key_path.is_absolute():
            examples_dir = Path(__file__).parent.parent.parent
            private_key_path = examples_dir / private_key_path
        if private_key_path.exists():
            kwargs["private_key_path"] = str(private_key_path)
            if config.hezor2_header_pk_password:
                kwargs["password"] = config.hezor2_header_pk_password.encode()
            print(f"  ✓ 使用私钥认证: {private_key_path}")
        else:
            print(f"  ⚠ 私钥文件不存在: {private_key_path}，将使用匿名密钥签名")

    return Hezor2SDK(**kwargs)


def example_1_pull_all_configs():
    """Example 1: 拉取全量配置（public + user 分组展示）。"""
    print("=== Example 1: 拉取全量配置 ===")
    print()

    async def run():
        async with _build_sdk() as sdk:
            data = await sdk.pull_configs()

            print(f"  ✓ 公共配置 (public): {len(data.public)} 项")
            for key, value in data.public.items():
                print(f"    {key} = {value}")

            print()
            print(f"  ✓ 用户配置 (user): {len(data.user)} 项")
            for key, value in data.user.items():
                print(f"    {key} = {value}")

            merged = data.merged()
            print()
            print(f"  ✓ 合并后配置: {len(merged)} 项（user 优先覆盖 public）")
            for key, value in merged.items():
                source = "user" if key in data.user else "public"
                print(f"    [{source}] {key} = {value}")

    try:
        asyncio.run(run())
    except Exception as e:
        print(f"  调用失败（需要连接 Hezor2 API）: {e}")

    print()


def example_2_pull_specific_keys():
    """Example 2: 按 key 列表过滤，只拉取指定配置项。"""
    print("=== Example 2: 按 key 列表过滤 ===")
    print()

    # 替换为实际存在的 key
    keys = ["EMBEDDING_BASE_URL_INNER", "MY_APP_URL", "DATABASE_HOST"]
    print(f"  请求 keys: {keys}")
    print()

    async def run():
        async with _build_sdk() as sdk:
            data = await sdk.pull_configs(keys=keys)

            merged = data.merged()
            print(f"  ✓ 返回 {len(merged)} 项（服务端仅返回存在的 key）")
            print()

            for key in keys:
                if key in merged:
                    source = "user" if key in data.user else "public"
                    print(f"  ✓ [{source}] {key} = {merged[key]}")
                else:
                    print(f"  - {key}（未找到）")

    try:
        asyncio.run(run())
    except Exception as e:
        print(f"  调用失败（需要连接 Hezor2 API）: {e}")

    print()


def example_3_inject_to_env():
    """Example 3: 拉取配置并注入当前进程环境变量。"""
    print("=== Example 3: 拉取配置 → 注入环境变量 ===")
    print()
    print("  场景：应用启动时一次性拉取所有配置，写入 os.environ，")
    print("        后续代码直接 os.getenv() 读取，无需再调用 SDK。")
    print()

    async def run():
        async with _build_sdk() as sdk:
            # 传入 global_base_url 以替换值中的 ${GLOBAL_BASE_URL} 占位符
            custom_base_url = config.hezor2_api_base_url
            data = await sdk.pull_configs(global_base_url=custom_base_url)

            configs = data.merged()

            before = {k: os.environ.get(k) for k in configs}
            os.environ.update(configs)

            print(f"  ✓ 已将 {len(configs)} 项配置注入 os.environ")
            print()

            for key, new_value in configs.items():
                old_value = before[key]
                if old_value is None:
                    print(f"  + {key} = {new_value}（新增）")
                elif old_value != new_value:
                    print(f"  ~ {key} = {new_value}（覆盖原值: {old_value}）")
                else:
                    print(f"  = {key} = {new_value}（未变）")

            print()
            print("  验证（通过 os.getenv 读取）:")
            for key in list(configs.keys())[:3]:
                print(f"    os.getenv({key!r}) → {os.getenv(key)!r}")
            if len(configs) > 3:
                print(f"    ... 共 {len(configs)} 项")

    try:
        asyncio.run(run())
    except Exception as e:
        print(f"  调用失败（需要连接 Hezor2 API）: {e}")

    print()


def list_examples():
    """列出所有可用示例。"""
    examples = {
        1: ("拉取全量配置（public + user 分组展示）", example_1_pull_all_configs),
        2: ("按 key 列表过滤，只拉取指定配置项", example_2_pull_specific_keys),
        3: ("拉取配置并注入当前进程环境变量", example_3_inject_to_env),
    }

    print("Available examples:")
    for num, (name, _) in examples.items():
        print(f"  {num}. {name}")
    print()
    print("Usage:")
    print(f"  uv run {sys.argv[0]} [example_number]")
    print(f"  uv run {sys.argv[0]}              # 运行所有示例")
    print(f"  uv run {sys.argv[0]} --list       # 列出示例")

    return examples


def main():
    """根据命令行参数运行示例。"""
    examples = {
        1: ("拉取全量配置（public + user 分组展示）", example_1_pull_all_configs),
        2: ("按 key 列表过滤，只拉取指定配置项", example_2_pull_specific_keys),
        3: ("拉取配置并注入当前进程环境变量", example_3_inject_to_env),
    }

    if len(sys.argv) > 1:
        arg = sys.argv[1]

        if arg in ["--list", "-l", "list"]:
            list_examples()
            return

        try:
            example_num = int(arg)
            if example_num not in examples:
                print(f"Error: Example {example_num} not found.")
                print()
                list_examples()
                sys.exit(1)

            name, func = examples[example_num]
            print("=" * 60)
            print(f"pull_configs - Example {example_num}")
            print("=" * 60)
            print()
            func()
            print("=" * 60)
            print(f"Example {example_num} completed successfully!")
            print("=" * 60)
            return

        except ValueError:
            print(f"Error: Invalid argument '{arg}'")
            print()
            list_examples()
            sys.exit(1)

    # 运行所有示例
    print("=" * 60)
    print("pull_configs - Usage Examples")
    print("=" * 60)
    print()

    for func in [example_1_pull_all_configs, example_2_pull_specific_keys, example_3_inject_to_env]:
        func()

    print("=" * 60)
    print("All examples completed successfully!")
    print("=" * 60)


if __name__ == "__main__":
    main()
