"""
环境管理模块
管理测试环境和配置
"""
import os
import json
from typing import Optional, Dict, Any, List
from pathlib import Path
from loguru import logger
from dataclasses import dataclass, field


@dataclass
class Environment:
    """环境配置"""
    name: str
    base_url: str = ""
    api_url: str = ""
    db_config: Dict[str, Any] = field(default_factory=dict)
    credentials: Dict[str, str] = field(default_factory=dict)
    custom: Dict[str, Any] = field(default_factory=dict)
    
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置值"""
        # 支持点号分隔的键
        if "." in key:
            keys = key.split(".")
            value = self.custom
            for k in keys:
                if isinstance(value, dict) and k in value:
                    value = value[k]
                else:
                    return default
            return value
        
        return self.custom.get(key, default)


class EnvironmentManager:
    """
    环境管理器
    管理多套测试环境配置
    """
    
    def __init__(self, config_dir: str = "./environments"):
        self.config_dir = Path(config_dir)
        self.config_dir.mkdir(parents=True, exist_ok=True)
        self._environments: Dict[str, Environment] = {}
        self._current: Optional[str] = None
    
    def add_environment(self, env: Environment):
        """添加环境"""
        self._environments[env.name] = env
        logger.info(f"环境已添加: {env.name}")
    
    def get_environment(self, name: str = None) -> Optional[Environment]:
        """获取环境"""
        name = name or self._current
        if not name:
            raise ValueError("未设置当前环境")
        return self._environments.get(name)
    
    def set_current(self, name: str):
        """设置当前环境"""
        if name not in self._environments:
            raise ValueError(f"环境不存在: {name}")
        self._current = name
        logger.info(f"当前环境: {name}")
    
    @property
    def current(self) -> Optional[Environment]:
        """获取当前环境"""
        return self.get_environment()
    
    def list_environments(self) -> List[str]:
        """列出所有环境"""
        return list(self._environments.keys())
    
    def save(self, name: str = None):
        """保存环境配置"""
        env = self.get_environment(name)
        if not env:
            return
        
        filepath = self.config_dir / f"{env.name}.json"
        data = {
            "name": env.name,
            "base_url": env.base_url,
            "api_url": env.api_url,
            "db_config": env.db_config,
            "credentials": env.credentials,
            "custom": env.custom,
        }
        
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        logger.info(f"环境配置已保存: {filepath}")
    
    def load(self, name: str) -> Environment:
        """加载环境配置"""
        filepath = self.config_dir / f"{name}.json"
        
        if not filepath.exists():
            raise FileNotFoundError(f"环境配置文件不存在: {filepath}")
        
        with open(filepath, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        env = Environment(
            name=data["name"],
            base_url=data.get("base_url", ""),
            api_url=data.get("api_url", ""),
            db_config=data.get("db_config", {}),
            credentials=data.get("credentials", {}),
            custom=data.get("custom", {}),
        )
        
        self._environments[name] = env
        logger.info(f"环境配置已加载: {name}")
        
        return env
    
    def load_all(self):
        """加载所有环境配置"""
        for filepath in self.config_dir.glob("*.json"):
            name = filepath.stem
            try:
                self.load(name)
            except Exception as e:
                logger.error(f"加载环境失败: {name}, error={e}")
    
    def delete(self, name: str):
        """删除环境"""
        if name in self._environments:
            del self._environments[name]
        
        filepath = self.config_dir / f"{name}.json"
        if filepath.exists():
            filepath.unlink()
        
        logger.info(f"环境已删除: {name}")


class ConfigManager:
    """
    配置管理器
    管理全局配置
    """
    
    _instance: Optional["ConfigManager"] = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._config: Dict[str, Any] = {}
        return cls._instance
    
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置"""
        keys = key.split(".")
        value = self._config
        
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
        
        return value
    
    def set(self, key: str, value: Any):
        """设置配置"""
        keys = key.split(".")
        config = self._config
        
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        
        config[keys[-1]] = value
    
    def load_from_file(self, filepath: str):
        """从文件加载配置"""
        with open(filepath, 'r', encoding='utf-8') as f:
            self._config.update(json.load(f))
        
        logger.info(f"配置已加载: {filepath}")
    
    def load_from_env(self, prefix: str = "APP_"):
        """从环境变量加载配置"""
        for key, value in os.environ.items():
            if key.startswith(prefix):
                config_key = key[len(prefix):].lower()
                self.set(config_key, value)
        
        logger.info(f"环境变量配置已加载: {prefix}*")
    
    def save_to_file(self, filepath: str):
        """保存配置到文件"""
        Path(filepath).parent.mkdir(parents=True, exist_ok=True)
        
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(self._config, f, ensure_ascii=False, indent=2)
        
        logger.info(f"配置已保存: {filepath}")
    
    def get_all(self) -> Dict[str, Any]:
        """获取所有配置"""
        return self._config.copy()


class SecretsManager:
    """
    密钥管理器
    安全管理敏感配置
    """
    
    def __init__(self, secrets_file: str = "./secrets.json"):
        self.secrets_file = Path(secrets_file)
        self._secrets: Dict[str, str] = {}
        self._loaded = False
    
    def load(self):
        """加载密钥"""
        if self.secrets_file.exists():
            with open(self.secrets_file, 'r', encoding='utf-8') as f:
                self._secrets = json.load(f)
            self._loaded = True
            logger.info("密钥已加载")
    
    def get(self, key: str) -> Optional[str]:
        """获取密钥"""
        if not self._loaded:
            self.load()
        return self._secrets.get(key)
    
    def set(self, key: str, value: str):
        """设置密钥"""
        self._secrets[key] = value
    
    def save(self):
        """保存密钥"""
        self.secrets_file.parent.mkdir(parents=True, exist_ok=True)
        
        with open(self.secrets_file, 'w', encoding='utf-8') as f:
            json.dump(self._secrets, f, ensure_ascii=False, indent=2)
        
        # 设置文件权限
        os.chmod(self.secrets_file, 0o600)
        
        logger.info("密钥已保存")
    
    def delete(self, key: str):
        """删除密钥"""
        if key in self._secrets:
            del self._secrets[key]
    
    def from_env(self, key: str, env_var: str = None):
        """从环境变量加载密钥"""
        env_var = env_var or key.upper()
        value = os.environ.get(env_var)
        
        if value:
            self._secrets[key] = value
            logger.info(f"密钥已从环境变量加载: {key}")


# 便捷函数
def get_config(key: str, default: Any = None) -> Any:
    """获取全局配置"""
    return ConfigManager().get(key, default)


def set_config(key: str, value: Any):
    """设置全局配置"""
    ConfigManager().set(key, value)


def get_secret(key: str) -> Optional[str]:
    """获取密钥"""
    return SecretsManager().get(key)
