"""
多账号管理器示例

用于管理多个微信公众号账号的认证和功能模块

Token获取优先级 (从高到低):
1. 自定义回调函数: WECHAT_ACCOUNT_X_TOKEN_GETTER_MODULE
2. 默认回调函数: WECHAT_TOKEN_SECRET
3. 微信官方API: WECHAT_ACCOUNT_X_APP_ID + APP_SECRET

使用方式:
1. 在 .env 中配置账号
2. 根据需要配置Token获取方式
3. 使用 AccountManager 获取对应账号的实例
"""

import os
import importlib
from typing import Dict, Optional, Callable

from xqcwechat import Auth, Asset, Draft, Publish, Comment


class AccountManager:
    """微信公众号多账号管理器"""

    def __init__(self, config_path: Optional[str] = None):
        """
        初始化账号管理器

        :param config_path: 配置文件路径，默认为 .env
        """
        from dotenv import load_dotenv

        load_dotenv(config_path)

        self.accounts: Dict[str, Dict] = {}
        self._auth_cache: Dict[str, Auth] = {}
        self._load_accounts()

    def _load_accounts(self):
        """从环境变量加载账号配置"""
        i = 1
        while True:
            # 检测账号配置 - 支持多种配置方式
            app_id = os.environ.get(f"WECHAT_ACCOUNT_{i}_APP_ID")
            app_secret = os.environ.get(f"WECHAT_ACCOUNT_{i}_APP_SECRET")
            token_app_id = os.environ.get(f"WECHAT_ACCOUNT_{i}_TOKEN_APP_ID")
            name = os.environ.get(f"WECHAT_ACCOUNT_{i}_NAME", f"账号{i}")
            token_module = os.environ.get(f"WECHAT_ACCOUNT_{i}_TOKEN_GETTER_MODULE")
            token_func = os.environ.get(
                f"WECHAT_ACCOUNT_{i}_TOKEN_GETTER_FUNC", "get_token"
            )

            # 判断是否有有效配置：
            # 1. 方式一：APP_ID + APP_SECRET（官方API）
            # 2. 方式二：TOKEN_APP_ID（默认回调）
            # 3. 方式三：TOKEN_GETTER_MODULE（自定义回调）
            has_config = (
                (app_id and app_secret) or  # 方式一
                token_app_id or              # 方式二
                token_module                 # 方式三
            )

            if not has_config:
                # 检查是否有全局的 WECHAT_TOKEN_SECRET 配置
                # 如果有且是第一个账号，则使用全局配置作为账号1
                if i == 1:
                    token_secret = os.environ.get("WECHAT_TOKEN_SECRET")
                    if token_secret:
                        # 从全局环境变量获取默认 app_id
                        default_app_id = os.environ.get("WECHAT_APP_ID") or os.environ.get("WECHAT_TOKEN_APP_ID")
                        self.accounts[name] = {
                            "app_id": default_app_id,
                            "app_secret": None,
                            "name": name,
                            "index": i,
                            "token_module": None,
                            "token_func": "get_token",
                            "use_token_secret": True,
                        }
                        i += 1
                        continue
                break

            self.accounts[name] = {
                "app_id": app_id or token_app_id,
                "app_secret": app_secret,
                "name": name,
                "index": i,
                "token_module": token_module,
                "token_func": token_func,
                "use_token_secret": bool(token_app_id or (i == 1 and os.environ.get("WECHAT_TOKEN_SECRET"))),
            }
            i += 1

        if self.accounts:
            print(f"✅ 已加载 {len(self.accounts)} 个账号: {list(self.accounts.keys())}")
        else:
            print("⚠️ 未检测到任何账号配置")

    def _get_token_getter(self, account: Dict) -> Optional[Callable]:
        """
        获取Token获取回调函数

        优先级:
        1. 自定义回调函数 (WECHAT_ACCOUNT_X_TOKEN_GETTER_MODULE)
        2. 默认回调函数 (WECHAT_TOKEN_SECRET)
        3. None (使用微信官方API)
        """
        token_module = account.get("token_module")
        token_func = account.get("token_func", "get_token")
        account_index = account.get("index", 1)

        if token_module:
            try:
                module = importlib.import_module(token_module)
                func = getattr(module, token_func)
                if account_index and callable(func):
                    from functools import partial

                    return partial(func, account_index=account_index)
                return func
            except Exception as e:
                print(f"❌ 加载自定义Token获取器失败: {e}")

        if account.get("use_token_secret"):
            token_secret = os.environ.get("WECHAT_TOKEN_SECRET")
            token_app_id = account.get("app_id")
            if token_secret:
                from functools import partial
                from xqcwechat import Auth

                return partial(
                    Auth._default_token_getter,
                    secret=token_secret,
                    app_id=token_app_id,
                )

        token_secret = os.environ.get("WECHAT_TOKEN_SECRET")
        if token_secret:
            try:
                module = importlib.import_module("token_getter")
                func = getattr(module, token_func)
                if account_index and callable(func):
                    from functools import partial

                    return partial(func, account_index=account_index)
                return func
            except Exception as e:
                print(f"❌ 加载默认Token获取器失败: {e}")

        return None

    def get_auth(self, account_name: Optional[str] = None) -> Auth:
        """
        获取指定账号的Auth实例

        :param account_name: 账号名称，默认使用第一个账号
        :return: Auth 认证实例
        """
        if not account_name:
            name, account = next(iter(self.accounts.items()))
        else:
            name = account_name
            account = self.accounts.get(account_name)
            if not account:
                raise ValueError(f"❌ 未找到账号: {account_name}")

        if name in self._auth_cache:
            return self._auth_cache[name]

        token_getter = self._get_token_getter(account)

        auth = Auth(
            app_id=account["app_id"],
            app_secret=account["app_secret"],
            access_token_getter=token_getter,
        )

        self._auth_cache[name] = auth
        return auth

    def get_asset(self, account_name: Optional[str] = None) -> Asset:
        """获取素材管理实例"""
        return Asset(self.get_auth(account_name))

    def get_draft(self, account_name: Optional[str] = None) -> Draft:
        """获取草稿管理实例"""
        return Draft(self.get_auth(account_name))

    def get_publish(self, account_name: Optional[str] = None) -> Publish:
        """获取发布管理实例"""
        return Publish(self.get_auth(account_name))

    def get_comment(self, account_name: Optional[str] = None) -> Comment:
        """获取留言管理实例"""
        return Comment(self.get_auth(account_name))

    def list_accounts(self) -> list:
        """列出所有账号"""
        return list(self.accounts.keys())

    def reload(self):
        """重新加载账号配置"""
        self._auth_cache.clear()
        self.accounts.clear()
        self._load_accounts()


_default_manager: Optional[AccountManager] = None


def get_manager(config_path: Optional[str] = None) -> AccountManager:
    """获取默认账号管理器 (单例)"""
    global _default_manager
    if _default_manager is None:
        _default_manager = AccountManager(config_path)
    return _default_manager


def reset_manager():
    """重置默认账号管理器"""
    global _default_manager
    _default_manager = None
