"""配置加载器"""

import json
import os
from pathlib import Path
from typing import Any, Dict, List, Optional, Union

from ..common import DEFAULT_CONFIG
from ..reference import GSDSTORE, INFO


class ConfigLoader:
    """配置加载器

    支持 JSON 和 YAML 格式的配置文件。
    """

    def __init__(self, config_path: Optional[str] = None):
        """初始化配置加载器

        Args:
            config_path: 配置文件路径，支持 .json 或 .yaml/.yml
        """
        self._config: Dict[str, Any] = DEFAULT_CONFIG.copy()
        self._config_path: Optional[Path] = None

        if config_path:
            self.load(config_path)

    def load(self, config_path: str) -> Dict[str, Any]:
        """加载配置文件

        Args:
            config_path: 配置文件路径

        Returns:
            配置字典

        Raises:
            FileNotFoundError: 配置文件不存在
            ValueError: 不支持的配置文件格式
        """
        path = Path(config_path)

        if not path.exists():
            raise FileNotFoundError(f"配置文件不存在: {config_path}")

        self._config_path = path
        suffix = path.suffix.lower()

        if suffix == '.json':
            config = self._load_json(path)
        elif suffix in ('.yaml', '.yml'):
            config = self._load_yaml(path)
        else:
            raise ValueError(f"不支持的配置文件格式: {suffix}")

        # 合并配置
        self._config.update(config)

        # 处理相对路径
        self._resolve_paths()

        # 更新全局存储
        GSDSTORE['START'] = self._config

        INFO(f"配置已加载: {config_path}")
        return self._config

    def _load_json(self, path: Path) -> Dict[str, Any]:
        """加载 JSON 配置文件"""
        with open(path, 'r', encoding='utf-8') as f:
            return json.load(f)

    def _load_yaml(self, path: Path) -> Dict[str, Any]:
        """加载 YAML 配置文件"""
        try:
            import yaml
            with open(path, 'r', encoding='utf-8') as f:
                return yaml.safe_load(f) or {}
        except ImportError:
            INFO("PyYAML 未安装，无法加载 YAML 配置", "WARNING")
            return {}

    def _resolve_paths(self) -> None:
        """解析配置中的相对路径"""
        if not self._config_path:
            return

        base_dir = self._config_path.parent

        # 处理测试用例文件路径
        if 'testCaseFile' in self._config:
            for case_file in self._config['testCaseFile']:
                if 'caseFilePath' in case_file:
                    case_path = Path(case_file['caseFilePath'])
                    if not case_path.is_absolute():
                        case_file['caseFilePath'] = str(base_dir / case_path)

        # 存储工作路径
        GSDSTORE['WORKPATH'] = {
            'config_dir': str(base_dir),
            'project_dir': str(base_dir.parent) if base_dir.name == 'data' else str(base_dir),
        }

    @property
    def config(self) -> Dict[str, Any]:
        """获取配置字典"""
        return self._config.copy()

    def get(self, key: str, default: Any = None) -> Any:
        """获取配置项

        Args:
            key: 配置键名，支持点号分隔的嵌套键 (如 "browser.headless")
            default: 默认值

        Returns:
            配置值或默认值
        """
        keys = key.split('.')
        value = self._config

        for k in keys:
            if isinstance(value, dict):
                value = value.get(k)
            else:
                return default

            if value is None:
                return default

        return value

    def set(self, key: str, value: Any) -> None:
        """设置配置项

        Args:
            key: 配置键名
            value: 配置值
        """
        keys = key.split('.')

        if len(keys) == 1:
            self._config[key] = value
        else:
            # 处理嵌套键
            target = self._config
            for k in keys[:-1]:
                if k not in target:
                    target[k] = {}
                target = target[k]
            target[keys[-1]] = value

    @property
    def browser(self) -> str:
        """浏览器类型"""
        return self._config.get('browser', 'chromium')

    @property
    def headless(self) -> bool:
        """是否无头模式"""
        return self._config.get('headless', False)

    @property
    def slow_mo(self) -> int:
        """操作延迟"""
        return self._config.get('slowMo', 0)

    @property
    def timeout(self) -> int:
        """默认超时"""
        return self._config.get('timeout', 30000)

    @property
    def trace(self) -> bool:
        """是否开启 trace"""
        return self._config.get('trace', False)

    @property
    def video(self) -> bool:
        """是否录制视频"""
        return self._config.get('video', False)

    @property
    def url(self) -> Optional[str]:
        """起始 URL"""
        return self._config.get('url')

    @property
    def test_case_files(self) -> List[Dict[str, Any]]:
        """测试用例文件配置"""
        return self._config.get('testCaseFile', [])

    @property
    def self_defined_parameters(self) -> Dict[str, Any]:
        """自定义参数"""
        return self._config.get('selfDefinedParameter', {})

    @property
    def retry_switch(self) -> bool:
        """是否开启重试"""
        return self._config.get('retrySwitch', False)

    @property
    def retry_count(self) -> int:
        """重试次数"""
        return self._config.get('retryCount', 1)

    def save(self, path: Optional[str] = None) -> None:
        """保存配置到文件

        Args:
            path: 保存路径，默认为加载时的路径
        """
        save_path = Path(path) if path else self._config_path

        if not save_path:
            raise ValueError("未指定保存路径")

        suffix = save_path.suffix.lower()

        if suffix == '.json':
            with open(save_path, 'w', encoding='utf-8') as f:
                json.dump(self._config, f, indent=4, ensure_ascii=False)
        elif suffix in ('.yaml', '.yml'):
            try:
                import yaml
                with open(save_path, 'w', encoding='utf-8') as f:
                    yaml.dump(self._config, f, default_flow_style=False, allow_unicode=True)
            except ImportError:
                INFO("PyYAML 未安装，无法保存 YAML 配置", "ERROR")
                raise

        INFO(f"配置已保存: {save_path}")
