"""
Voiceprint Client - 声纹识别平台客户端

用于与外部声纹识别平台进行交互，支持声纹人的增删查操作。
"""
import logging
import time
import httpx

from src.config import ASR_BASE_URL

logger = logging.getLogger(__name__)


class VoiceprintClient:
    """
    声纹识别平台客户端
    
    用于与外部声纹识别平台进行交互，支持声纹人的增删查操作
    """
    
    def __init__(self, database_name='NB', collection_name='voice'):
        """
        初始化声纹客户端
        
        Args:
            database_name: 数据库名称，默认为 'NB'
            collection_name: 集合名称，默认为 'voice'
        """
        self.base_url = ASR_BASE_URL
        self.database_name = database_name
        self.collection_name = collection_name
        self.timeout = httpx.Timeout(
            connect=10.0,
            read=30.0,
            write=60.0,
            pool=10.0
        )
        # 使用持久化 httpx.Client 复用连接池
        self._client = httpx.Client(
            base_url=self.base_url,
            timeout=self.timeout,
            verify=True
        )
        self._max_retries = 3
        logger.info(f"声纹客户端初始化完成，目标平台：{self.base_url}")
    
    def _make_request(self, method, endpoint, **kwargs):
        """
        发送 HTTP 请求到声纹平台（带重试机制）
        
        Args:
            method: HTTP 方法 (GET, POST, DELETE 等)
            endpoint: API 端点路径
            **kwargs: 传递给 httpx.request 的其他参数
        
        Returns:
            dict: API 响应的 JSON 数据
        
        Raises:
            Exception: 重试失败后抛出异常
        """
        url = f"{self.base_url}{endpoint}"
        last_exception = None
        
        for attempt in range(1, self._max_retries + 1):
            try:
                response = self._client.request(method, url, **kwargs)
                response.raise_for_status()
                return response.json()
            except httpx.HTTPStatusError as e:
                logger.error(f"声纹 API 错误（第 {attempt}/{self._max_retries} 次尝试）：{e.response.status_code} - {e.response.text}")
                last_exception = e
                break  # HTTP 状态错误不重试
            except httpx.ConnectError as e:
                logger.warning(f"声纹连接失败（第 {attempt}/{self._max_retries} 次尝试）：{e}")
                last_exception = e
            except httpx.TimeoutException as e:
                logger.warning(f"声纹请求超时（第 {attempt}/{self._max_retries} 次尝试）：{e}")
                last_exception = e
            except httpx.RequestError as e:
                logger.warning(f"声纹请求错误（第 {attempt}/{self._max_retries} 次尝试）：{e}")
                last_exception = e
            
            if attempt < self._max_retries:
                wait_time = 2 ** (attempt - 1)  # 指数退避：1s, 2s, 4s
                logger.info(f"等待 {wait_time} 秒后重试...")
                time.sleep(wait_time)
        
        # 所有重试耗尽
        if isinstance(last_exception, httpx.ConnectError):
            raise Exception(f"无法连接到声纹平台（已重试 {self._max_retries} 次）")
        elif isinstance(last_exception, httpx.TimeoutException):
            raise Exception(f"声纹平台请求超时（已重试 {self._max_retries} 次）")
        elif isinstance(last_exception, httpx.HTTPStatusError):
            raise Exception(f"声纹平台请求失败：{last_exception.response.status_code}")
        else:
            raise Exception(f"声纹平台请求失败（已重试 {self._max_retries} 次）：{last_exception}")
    
    def get_voice_names(self):
        """
        获取声纹人列表
        
        Returns:
            dict: 包含声纹人列表的响应
        """
        params = {
            'database_name': self.database_name,
            'collection_name': self.collection_name
        }
        return self._make_request('GET', '/get_voice_name', params=params)
    
    def add_voiceprint(self, name, audio_file):
        """
        添加声纹人
        
        Args:
            name: 声纹人姓名
            audio_file: 音频文件对象
        
        Returns:
            dict: API 响应
        """
        data = {
            'voice_name': name,
            'database_name': self.database_name,
            'collection_name': self.collection_name
        }
        files = {'voice_file': audio_file}
        return self._make_request('POST', '/voice_insert', data=data, files=files)
    
    def delete_voiceprint(self, name):
        """
        删除声纹人
        
        Args:
            name: 要删除的声纹人姓名
        
        Returns:
            dict: API 响应
        """
        params = {
            'database_name': self.database_name,
            'collection_name': self.collection_name,
            'name': name
        }
        return self._make_request('DELETE', '/delete_voice', params=params)
    
    def close(self):
        """关闭底层 HTTP 客户端"""
        if self._client:
            self._client.close()


# 全局声纹客户端实例（延迟初始化）
_voiceprint_client = None

def voiceprint_client():
    """获取声纹客户端实例（延迟初始化以避免循环导入）"""
    global _voiceprint_client
    if _voiceprint_client is None:
        _voiceprint_client = VoiceprintClient()
    return _voiceprint_client
