"""
ChunkHive Ranking Engine
========================

Re-ranks semantic search results using multi-factor scoring.

Combines:
- Semantic similarity
- Keyword relevance
- Structural importance
- Metadata signals
- Dependency signals
"""

from typing import List, Any, Dict
from dataclasses import dataclass

from .scoring.aggregator import AggregatorScorer
from .scoring.base import ScoreResult


@dataclass
class RankedResult:
    chunk: Any
    score: float
    confidence: float
    details: Dict


class RankingEngine:
    """
    Re-ranks candidate chunks using AggregatorScorer.
    """

    def __init__(self, aggregator: AggregatorScorer):
        self.aggregator = aggregator

    # ----------------------------
    # Public API
    # ----------------------------
    def rank(
        self,
        query: str,
        candidates: List[Any],
        top_k: int = 5,
        explain: bool = False,
    ) -> List[RankedResult]:

        ranked_results: List[RankedResult] = []

        for chunk in candidates:
            try:
                result: ScoreResult = self.aggregator.score(query, chunk)
                final_score = float(result.score)

            except Exception:
                # Never let one bad chunk break ranking
                final_score = 0.0
                result = ScoreResult(score=0.0, details={})

            confidence = self._compute_confidence(final_score)

            ranked_results.append(
                RankedResult(
                    chunk=chunk,
                    score=final_score,
                    confidence=confidence,
                    details=result.details if explain else {},
                )
            )

        # Stable sort (important for deterministic ranking)
        ranked_results.sort(
            key=lambda x: (x.score, x.confidence),
            reverse=True
        )

        return ranked_results[:top_k]

    # ----------------------------
    # Internal Helpers
    # ----------------------------
    def _compute_confidence(self, score: float) -> float:
        """
        Converts raw score to normalized confidence.
        Keeps deterministic behavior.
        """

        if score <= 0:
            return 0.0

        # Simple bounded normalization
        # You can replace with sigmoid later if needed
        return min(score / 5.0, 1.0)
