"""主客户端模块"""

from typing import Optional

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

from .chart import ChartService
from .config import Config
from .exceptions import ConfigError
from .storage import StorageService


class Lims2Client:
    """Lims2 SDK 主客户端

    提供图表和文件存储等服务的统一入口。典型用法：

    Example:
        >>> from lims2 import Lims2Client
        >>> client = Lims2Client()
        >>>
        >>> # 上传图表
        >>> client.chart.upload("plot.json", project_id="proj_001")
        >>>
        >>> # 上传文件
        >>> client.storage.upload_file("results.csv", project_id="proj_001")
    """

    def __init__(self, api_url: Optional[str] = None, token: Optional[str] = None):
        """初始化客户端

        Args:
            api_url: API 地址（可选，默认从环境变量读取）
            token: API Token（可选，默认从环境变量读取）
        """
        # 初始化配置
        self.config = Config(api_url, token)

        # 验证配置
        try:
            self.config.validate()
        except ValueError as e:
            raise ConfigError(str(e))

        # 创建带连接池优化的 HTTP 会话
        self.session = self._create_session()
        self.session.headers.update(self.config.get_headers())

        # 直接初始化服务
        self.chart = ChartService(self)
        self.storage = StorageService(self)

    def _create_session(self) -> requests.Session:
        """创建配置了重试策略的会话

        针对网络不稳定问题：
        - 配置自动重试机制处理 DNS 解析失败
        - 指数退避避免频繁重试
        """
        session = requests.Session()

        # 配置重试策略
        retry_strategy = Retry(
            total=3,  # 总重试次数
            backoff_factor=0.5,  # 重试延迟：0.5, 1, 2 秒
            status_forcelist=[429, 500, 502, 503, 504],  # 需要重试的状态码
            allowed_methods=[
                "HEAD",
                "GET",
                "POST",
                "PUT",
                "DELETE",
                "OPTIONS",
                "TRACE",
            ],
            # 对连接错误也进行重试
            raise_on_status=False,
        )

        # 配置连接池（串行上传时使用默认值即可）
        adapter = HTTPAdapter(max_retries=retry_strategy)

        # 为 HTTP 和 HTTPS 设置适配器
        session.mount("http://", adapter)
        session.mount("https://", adapter)

        # 设置合理的超时时间
        session.timeout = self.config.timeout

        return session

    def close(self) -> None:
        """关闭客户端，清理资源"""
        if hasattr(self, "session"):
            self.session.close()

    def __enter__(self):
        """上下文管理器入口"""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.close()

    def __repr__(self) -> str:
        return f"Lims2Client(api_url={self.config.api_url!r})"
