"""
请求分发器

负责执行单个候选请求
"""

from typing import Any, Callable, Optional, Tuple

from sqlalchemy.orm import Session

from src.core.enums import APIFormat
from src.core.logger import logger
from src.models.database import ApiKey
from src.services.cache.aware_scheduler import CacheAwareScheduler, ProviderCandidate
from src.services.request.candidate import RequestCandidateService
from src.services.request.executor import RequestExecutor



class RequestDispatcher:
    """
    请求分发器 - 负责执行单个候选请求

    职责：
    1. 执行请求并返回结果
    2. 更新候选状态（pending -> success/failed）
    3. 设置缓存亲和性（成功时）
    """

    def __init__(
        self,
        db: Session,
        request_executor: RequestExecutor,
        cache_scheduler: Optional[CacheAwareScheduler] = None,
    ) -> None:
        """
        初始化请求分发器

        Args:
            db: 数据库会话
            request_executor: 请求执行器
            cache_scheduler: 缓存调度器（可选）
        """
        self.db = db
        self.request_executor = request_executor
        self.cache_scheduler = cache_scheduler

    async def dispatch(
        self,
        candidate: ProviderCandidate,
        candidate_index: int,
        retry_index: int,
        candidate_record_id: str,
        user_api_key: ApiKey,
        request_func: Callable[..., Any],
        request_id: Optional[str],
        api_format: APIFormat,
        model_name: str,
        affinity_key: str,
        global_model_id: str,
        attempt_counter: int,
        max_attempts: int,
        is_stream: bool = False,
    ) -> Tuple[Any, str, str, str, str, str]:
        """
        执行请求并返回结果

        Args:
            candidate: 候选对象
            candidate_index: 候选索引
            retry_index: 重试索引
            candidate_record_id: 候选记录 ID
            user_api_key: 用户 API Key
            request_func: 请求函数
            request_id: 请求 ID
            api_format: API 格式
            model_name: 模型名称
            affinity_key: 亲和性标识符（通常为API Key ID）
            global_model_id: GlobalModel ID（规范化的模型标识，用于缓存亲和性）
            attempt_counter: 尝试计数
            max_attempts: 最大尝试次数
            is_stream: 是否为流式请求

        Returns:
            (response, provider_name, candidate_record_id, provider_id, endpoint_id, key_id)

        Raises:
            ExecutionError: 执行失败时
        """
        provider = candidate.provider
        endpoint = candidate.endpoint
        key = candidate.key

        # 显式转换为 str
        provider_id = str(provider.id)
        provider_name = str(provider.name)
        endpoint_id = str(endpoint.id)
        key_id = str(key.id)
        cache_ttl_minutes = int(key.cache_ttl_minutes or 0)
        provider_supports_caching = cache_ttl_minutes > 0
        provider_cache_ttl_seconds: Optional[int] = (
            cache_ttl_minutes * 60 if cache_ttl_minutes > 0 else None
        )

        # 更新状态为 pending
        RequestCandidateService.update_candidate_status(
            db=self.db, candidate_id=candidate_record_id, status="pending"
        )

        # 执行请求
        execution_result = await self.request_executor.execute(
            candidate=candidate,
            candidate_id=candidate_record_id,
            candidate_index=candidate_index,
            user_api_key=user_api_key,
            request_func=request_func,
            request_id=request_id,
            api_format=api_format,
            model_name=model_name,
            is_stream=is_stream,
        )

        context = execution_result.context
        elapsed_ms = context.elapsed_ms or 0

        # 流式请求：标记为 streaming 状态（请求尚未完成）
        # 非流式请求：标记为 success 状态
        # 注意：executor.execute() 内部已经处理了状态标记，这里不再重复
        # 流式请求的 success 状态会在流完成后由 _record_stream_stats 方法标记

        # 设置缓存亲和性
        if provider_supports_caching and self.cache_scheduler is not None:
            try:
                api_format_str = (
                    api_format.value if isinstance(api_format, APIFormat) else api_format
                )
                await self.cache_scheduler.set_cache_affinity(
                    affinity_key=affinity_key,
                    provider_id=provider_id,
                    endpoint_id=endpoint_id,
                    key_id=key_id,
                    api_format=api_format_str,
                    global_model_id=global_model_id,
                    ttl=provider_cache_ttl_seconds,
                )
            except Exception as cache_exc:
                logger.warning(f"  [{request_id}] 设置缓存亲和性失败: {cache_exc}")

        logger.debug(f"  [{request_id}] 请求成功: Provider={provider_name}, 耗时={elapsed_ms}ms")

        return (
            execution_result.response,
            provider_name,
            candidate_record_id,
            provider_id,
            endpoint_id,
            key_id,
        )
