"""
配置文件读取工具模块

解析系统配置文件（INI格式），支持：
- INI文件解析
- 多Section配置
- 类型转换（字符串、整数、浮点数、字典）
- 环境判断（开发/测试/生产）

注意：底层基础工具，禁止引入过多依赖

Example:
    >>> reader = ConfigReader.get_instance("config.ini")
    >>> db_host = reader.get("database", "host")
    >>> db_port = reader.get_int("database", "port")
"""
import os
import json
import configparser
from typing import Dict, Any, Optional


class ConfigError(Exception):
    """配置文件错误异常"""
    pass


class ConfigUtil:
    """
    配置工具类

    提供静态方法进行配置文件路径处理和读取。

    Example:
        >>> sys_path = ConfigUtil.get_sys_path(__file__)
        >>> conf_dict = ConfigUtil.read_conf("config.ini")
    """

    @staticmethod
    def get_sys_path(py_file: str, sys_name: Optional[str] = None) -> str:
        """
        获取系统根路径

        根据Python文件路径推断系统根目录。

        Args:
            py_file: Python文件路径（通常传入__file__）
            sys_name: 系统名称（可选）

        Returns:
            系统根目录路径
        """
        file_path = str(os.path.abspath(py_file))
        idx_sys_name = -1

        if sys_name and len(str(sys_name)) > 0:
            idx_sys_name = file_path.rfind(sys_name)

        idx_src = file_path.rfind("/src/")
        idx_tests = file_path.rfind("/tests/")

        if idx_sys_name > 0:
            sys_path = file_path[0:idx_sys_name + len(sys_name)]
        elif idx_src > 0:
            sys_path = file_path[0:idx_src]
        elif idx_tests > 0:
            sys_path = file_path[0:idx_tests]
        else:
            sys_path = "../"

        return sys_path

    @staticmethod
    def get_env(
        conf_file: str,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> str:
        """
        获取系统环境配置

        Args:
            conf_file: 配置文件路径
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            环境标识字符串
        """
        config_reader = ConfigReader.get_instance(conf_file)
        return config_reader.get(conf_section, conf_key)

    @staticmethod
    def is_dev(
        conf_file: str,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为开发环境

        Args:
            conf_file: 配置文件路径
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为开发环境
        """
        return ConfigUtil.get_env(conf_file, conf_section, conf_key) == "DEV"

    @staticmethod
    def is_test(
        conf_file: str,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为测试环境

        Args:
            conf_file: 配置文件路径
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为测试环境
        """
        return ConfigUtil.get_env(conf_file, conf_section, conf_key) == "TEST"

    @staticmethod
    def is_prod(
        conf_file: str,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为生产环境

        Args:
            conf_file: 配置文件路径
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为生产环境
        """
        return ConfigUtil.get_env(conf_file, conf_section, conf_key).startswith("PROD")

    @staticmethod
    def read_conf(conf_file: str) -> Dict[str, Dict[str, str]]:
        """
        读取配置文件

        Args:
            conf_file: 配置文件路径

        Returns:
            嵌套字典结构：{section: {key: value}}

        Raises:
            ConfigError: 配置文件不存在时抛出

        Example:
            >>> conf = ConfigUtil.read_conf("config.ini")
            >>> print(conf["database"]["host"])
        """
        if not os.path.exists(conf_file) or not os.path.isfile(conf_file):
            raise ConfigError(f"Config file not exist: {conf_file}")

        conf_parse = configparser.ConfigParser()
        conf_parse.read(conf_file, encoding="utf-8")

        conf_dict: Dict[str, Dict[str, str]] = {}
        conf_sections = conf_parse.sections()

        for section in conf_sections:
            section_dict: Dict[str, str] = {}
            keys = conf_parse.options(section)
            for key in keys:
                section_dict[key] = conf_parse.get(section, key)
            conf_dict[section] = section_dict

        return conf_dict


class ConfigReader:
    """
    配置文件读取器类

    封装配置字典，提供便捷的配置值获取方法。

    Attributes:
        conf_dict: 配置字典

    Example:
        >>> reader = ConfigReader.get_instance("config.ini")
        >>> host = reader.get("database", "host")
        >>> port = reader.get_int("database", "port")
    """

    def __init__(self, conf_dict: Dict[str, Dict[str, str]]):
        """
        初始化配置读取器

        Args:
            conf_dict: 配置字典
        """
        self.conf_dict: Dict[str, Dict[str, str]] = conf_dict

    @staticmethod
    def get_instance(conf_file: str) -> "ConfigReader":
        """
        创建ConfigReader实例

        Args:
            conf_file: 配置文件路径

        Returns:
            ConfigReader实例
        """
        conf_dict = ConfigUtil.read_conf(conf_file)
        return ConfigReader(conf_dict)

    def get(self, section: str, key: str, default: str = "") -> str:
        """
        获取字符串配置值

        Args:
            section: Section名称
            key: 配置键名
            default: 默认值

        Returns:
            配置值字符串
        """
        if section in self.conf_dict:
            section_dict = self.conf_dict[section]
            if key in section_dict:
                return section_dict[key]
        return default

    def get_int(self, section: str, key: str, default: int = 0) -> int:
        """
        获取整数配置值

        Args:
            section: Section名称
            key: 配置键名
            default: 默认值

        Returns:
            配置值整数
        """
        if section in self.conf_dict:
            section_dict = self.conf_dict[section]
            if key in section_dict:
                return int(section_dict[key])
        return default

    def get_float(self, section: str, key: str, default: float = 0.0) -> float:
        """
        获取浮点数配置值

        Args:
            section: Section名称
            key: 配置键名
            default: 默认值

        Returns:
            配置值浮点数
        """
        if section in self.conf_dict:
            section_dict = self.conf_dict[section]
            if key in section_dict:
                return float(section_dict[key])
        return default

    def get_dict(self, section: str, key: str) -> Dict[str, Any]:
        """
        获取字典配置值

        配置值应为JSON格式字符串。

        Args:
            section: Section名称
            key: 配置键名

        Returns:
            解析后的字典
        """
        if section in self.conf_dict:
            section_dict = self.conf_dict[section]
            if key in section_dict:
                value = section_dict[key]
                return json.loads(value)
        return {}

    def get_section_dict(self, section: str) -> Dict[str, str]:
        """
        获取整个Section的配置字典

        Args:
            section: Section名称

        Returns:
            Section配置字典
        """
        if section in self.conf_dict:
            return self.conf_dict[section]
        return {}

    def get_env(
        self,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> str:
        """
        获取系统环境配置

        Args:
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            环境标识字符串
        """
        return self.get(conf_section, conf_key)

    def is_dev(
        self,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为开发环境

        Args:
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为开发环境
        """
        return self.get_env(conf_section, conf_key) == "DEV"

    def is_test(
        self,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为测试环境

        Args:
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为测试环境
        """
        return self.get_env(conf_section, conf_key) == "TEST"

    def is_prod(
        self,
        conf_section: str = "sys_info",
        conf_key: str = "sys_env"
    ) -> bool:
        """
        判断是否为生产环境

        Args:
            conf_section: Section名称
            conf_key: 配置键名

        Returns:
            是否为生产环境
        """
        return self.get_env(conf_section, conf_key).startswith("PROD")


if __name__ == "__main__":
    pass
