"""HTTP 传输层实现"""
import gzip
import json
import logging
from typing import List, Dict, Any
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

from .base import BaseTransport
from ..utils.circuit_breaker import CircuitBreaker
from ..client.config import LogConfig

logger = logging.getLogger(__name__)


class HTTPTransport(BaseTransport):
    """HTTP 传输层实现
    
    使用 HTTP 协议发送日志到服务器
    """
    
    def __init__(self, config: LogConfig):
        """初始化 HTTP 传输层
        
        Args:
            config: 日志配置
        """
        self.config = config
        self.server_url = config.server_url.rstrip("/")
        self.endpoint = f"{self.server_url}/api/v1/logs/batch"
        
        # 创建会话（支持连接池）
        self.session = requests.Session()
        
        # 配置重试策略（仅对网络错误重试，不对 HTTP 错误重试）
        retry_strategy = Retry(
            total=0,  # 不使用 requests 的重试，我们自己实现
            backoff_factor=0,
            status_forcelist=[],
        )
        
        adapter = HTTPAdapter(
            max_retries=retry_strategy,
            pool_connections=10,
            pool_maxsize=20
        )
        
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)
        
        # 设置默认超时
        self.timeout = config.timeout
        
        # 创建熔断器
        self.circuit_breaker = CircuitBreaker(
            failure_threshold=config.circuit_breaker_threshold,
            timeout=config.circuit_breaker_timeout
        )
        
        # 统计信息
        self.stats = {
            "total_sent": 0,
            "total_failed": 0,
            "total_logs": 0
        }
        
        logger.info(f"HTTP 传输层已初始化: {self.endpoint}")
    
    def send(self, logs: List[Dict[str, Any]]) -> bool:
        """发送日志批次
        
        Args:
            logs: 日志列表
            
        Returns:
            是否发送成功
        """
        if not logs:
            return True
        
        # 检查熔断器
        if self.circuit_breaker.is_open():
            logger.warning("熔断器已打开，拒绝发送")
            self.stats["total_failed"] += 1
            return False
        
        try:
            # 准备数据
            payload = {
                "app_name": self.config.app_name,
                "logs": logs
            }
            
            # 序列化为 JSON
            data = json.dumps(payload).encode("utf-8")
            
            # 压缩（如果启用）
            headers = {"Content-Type": "application/json"}
            if self.config.enable_compression:
                data = gzip.compress(data)
                headers["Content-Encoding"] = "gzip"
            
            # 通过熔断器发送请求
            response = self.circuit_breaker.call(
                self._send_request,
                data,
                headers
            )
            
            # 检查响应状态
            if response.status_code == 200:
                self.stats["total_sent"] += 1
                self.stats["total_logs"] += len(logs)
                return True
            else:
                logger.error(
                    f"服务器返回错误: {response.status_code}, "
                    f"响应: {response.text}"
                )
                self.stats["total_failed"] += 1
                return False
        
        except Exception as e:
            logger.error(f"发送日志失败: {e}", exc_info=True)
            self.stats["total_failed"] += 1
            return False
    
    def _send_request(self, data: bytes, headers: Dict[str, str]) -> requests.Response:
        """发送 HTTP 请求（供熔断器调用）
        
        Args:
            data: 请求体数据
            headers: 请求头
            
        Returns:
            响应对象
        """
        response = self.session.post(
            self.endpoint,
            data=data,
            headers=headers,
            timeout=self.timeout
        )
        
        # 对于非 2xx 状态码，抛出异常
        response.raise_for_status()
        
        return response
    
    def health_check(self) -> bool:
        """健康检查
        
        Returns:
            服务器是否可达
        """
        try:
            health_url = f"{self.server_url}/api/v1/health"
            response = self.session.get(health_url, timeout=3)
            return response.status_code == 200
        except Exception as e:
            logger.debug(f"健康检查失败: {e}")
            return False
    
    def close(self):
        """关闭连接"""
        if self.session:
            self.session.close()
            logger.info("HTTP 传输层已关闭")
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息
        
        Returns:
            统计信息字典
        """
        return {
            **self.stats,
            "circuit_breaker_state": self.circuit_breaker.get_state(),
            "endpoint": self.endpoint
        }
