"""
Pipeline Base Classes.
[AC-AISVC-RES-01~15] Pipeline 抽象基类。
"""

import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Any

from app.services.retrieval.base import RetrievalContext, RetrievalHit, RetrievalResult
from app.services.retrieval.strategy.config import FilterMode

logger = logging.getLogger(__name__)


@dataclass
class MetadataFilterResult:
    """元数据过滤结果。"""
    filter_dict: dict[str, Any] = field(default_factory=dict)
    filter_mode: FilterMode = FilterMode.NONE
    confidence: float | None = None
    missing_required_slots: list[dict[str, str]] = field(default_factory=list)
    debug_info: dict[str, Any] = field(default_factory=dict)


@dataclass
class PipelineContext:
    """Pipeline 执行上下文。"""
    retrieval_ctx: RetrievalContext
    metadata_filter: MetadataFilterResult | None = None
    use_reranker: bool = False
    use_react: bool = False
    react_iteration: int = 0
    previous_results: list[RetrievalHit] = field(default_factory=list)
    extra: dict[str, Any] = field(default_factory=dict)
    
    @property
    def tenant_id(self) -> str:
        return self.retrieval_ctx.tenant_id
    
    @property
    def query(self) -> str:
        return self.retrieval_ctx.query
    
    @property
    def session_id(self) -> str | None:
        return self.retrieval_ctx.session_id
    
    @property
    def kb_ids(self) -> list[str] | None:
        return self.retrieval_ctx.kb_ids


@dataclass
class PipelineResult:
    """Pipeline 执行结果。"""
    retrieval_result: RetrievalResult
    pipeline_name: str = ""
    used_reranker: bool = False
    used_react: bool = False
    react_iterations: int = 0
    metadata_filter_applied: bool = False
    fallback_triggered: bool = False
    fallback_reason: str | None = None
    latency_ms: float = 0.0
    diagnostics: dict[str, Any] = field(default_factory=dict)
    
    @property
    def hits(self) -> list[RetrievalHit]:
        return self.retrieval_result.hits
    
    @property
    def is_empty(self) -> bool:
        return self.retrieval_result.is_empty


class BasePipeline(ABC):
    """Pipeline 抽象基类。【AC-AISVC-RES-01, AC-AISVC-RES-02】"""
    
    @property
    @abstractmethod
    def name(self) -> str:
        """Pipeline 名称。"""
        pass
    
    @property
    @abstractmethod
    def description(self) -> str:
        """Pipeline 描述。"""
        pass
    
    @abstractmethod
    async def retrieve(self, ctx: PipelineContext) -> PipelineResult:
        """执行检索。"""
        pass
    
    @abstractmethod
    async def health_check(self) -> bool:
        """健康检查。"""
        pass
    
    def _create_empty_result(
        self,
        ctx: PipelineContext,
        error: str | None = None,
        latency_ms: float = 0.0,
    ) -> PipelineResult:
        """创建空结果。"""
        diagnostics = {"error": error} if error else {}
        return PipelineResult(
            retrieval_result=RetrievalResult(hits=[], diagnostics=diagnostics),
            pipeline_name=self.name,
            latency_ms=latency_ms,
            diagnostics=diagnostics,
        )
