"""gRPC 传输层实现"""
import logging
from typing import List, Dict, Any

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

logger = logging.getLogger(__name__)


class GRPCTransport(BaseTransport):
    """gRPC 传输层实现
    
    使用 gRPC 协议发送日志到服务器（高性能场景）
    """
    
    def __init__(self, config: LogConfig):
        """初始化 gRPC 传输层
        
        Args:
            config: 日志配置
        """
        self.config = config
        self.server_url = config.server_url
        
        # 创建熔断器
        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
        }
        
        # gRPC 相关对象（延迟初始化）
        self.channel = None
        self.stub = None
        
        try:
            self._init_grpc()
            logger.info(f"gRPC 传输层已初始化: {self.server_url}")
        except ImportError as e:
            logger.error(
                f"gRPC 依赖未安装: {e}\n"
                "请运行: pip install grpcio grpcio-tools"
            )
            raise
    
    def _init_grpc(self):
        """初始化 gRPC 连接"""
        try:
            import grpc
            
            # 尝试导入生成的代码
            try:
                from ..proto import log_pb2, log_pb2_grpc
            except ImportError:
                logger.warning(
                    "gRPC 协议文件未生成，请运行: \n"
                    "python -m grpc_tools.protoc -I. --python_out=. "
                    "--grpc_python_out=. proto/log.proto"
                )
                # 使用占位符，实际使用时需要生成
                raise ImportError("gRPC 协议文件未生成")
            
            # 创建通道
            self.channel = grpc.insecure_channel(
                self.server_url,
                options=[
                    ('grpc.max_send_message_length', 50 * 1024 * 1024),
                    ('grpc.max_receive_message_length', 50 * 1024 * 1024),
                ]
            )
            
            # 创建 stub
            self.stub = log_pb2_grpc.LogServiceStub(self.channel)
            
            # 保存协议类
            self.log_pb2 = log_pb2
            
        except ImportError:
            # 如果 gRPC 未安装，提供友好的错误信息
            logger.error("gRPC 模块未安装或协议文件未生成")
            raise
    
    def send(self, logs: List[Dict[str, Any]]) -> bool:
        """发送日志批次
        
        Args:
            logs: 日志列表
            
        Returns:
            是否发送成功
        """
        if not logs:
            return True
        
        # 检查 gRPC 是否初始化
        if self.stub is None:
            logger.error("gRPC 未正确初始化")
            self.stats["total_failed"] += 1
            return False
        
        # 检查熔断器
        if self.circuit_breaker.is_open():
            logger.warning("熔断器已打开，拒绝发送")
            self.stats["total_failed"] += 1
            return False
        
        try:
            # 转换为 protobuf 格式
            log_entries = []
            for log in logs:
                entry = self.log_pb2.LogEntry(
                    timestamp=log.get("timestamp", ""),
                    level=log.get("level", "INFO"),
                    message=log.get("message", ""),
                    metadata={
                        k: str(v) for k, v in log.get("metadata", {}).items()
                    }
                )
                log_entries.append(entry)
            
            # 创建批次
            batch = self.log_pb2.LogBatch(
                app_name=self.config.app_name,
                logs=log_entries
            )
            
            # 通过熔断器发送
            response = self.circuit_breaker.call(
                self._send_batch,
                batch
            )
            
            # 检查响应
            if response.success:
                self.stats["total_sent"] += 1
                self.stats["total_logs"] += len(logs)
                return True
            else:
                logger.error(f"服务器返回失败: {response.message}")
                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_batch(self, batch):
        """发送批次（供熔断器调用）
        
        Args:
            batch: LogBatch 对象
            
        Returns:
            SendResponse 对象
        """
        response = self.stub.SendLogs(
            batch,
            timeout=self.config.timeout
        )
        
        if not response.success:
            raise Exception(f"发送失败: {response.message}")
        
        return response
    
    def health_check(self) -> bool:
        """健康检查
        
        Returns:
            服务器是否可达
        """
        if self.stub is None:
            return False
        
        try:
            request = self.log_pb2.HealthRequest()
            response = self.stub.HealthCheck(request, timeout=3)
            return response.healthy
        except Exception as e:
            logger.debug(f"健康检查失败: {e}")
            return False
    
    def close(self):
        """关闭连接"""
        if self.channel:
            self.channel.close()
            logger.info("gRPC 传输层已关闭")
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息
        
        Returns:
            统计信息字典
        """
        return {
            **self.stats,
            "circuit_breaker_state": self.circuit_breaker.get_state(),
            "server": self.server_url
        }
