"""Reciprocal Rank Fusion for hybrid recall (vector + FTS)."""

from neo_cortex.models import RecalledMemory


def reciprocal_rank_fusion(
    vector_results: list[RecalledMemory],
    fts_results: list[RecalledMemory],
    k: int = 60,
    n: int = 10,
) -> list[RecalledMemory]:
    """Combine vector and FTS results using Reciprocal Rank Fusion.

    RRF score = sum(1 / (k + rank_i)) for each ranking list.
    Documents appearing in both lists get boosted naturally.

    Args:
        vector_results: Results from vector similarity search
        fts_results: Results from FTS5 keyword search
        k: Smoothing constant (default 60, higher = more uniform)
        n: Max results to return
    """
    rrf_scores: dict[str, float] = {}
    record_map: dict[str, RecalledMemory] = {}

    for rank, m in enumerate(vector_results, start=1):
        rrf_scores[m.record.id] = rrf_scores.get(m.record.id, 0) + 1 / (k + rank)
        record_map[m.record.id] = m

    for rank, m in enumerate(fts_results, start=1):
        rrf_scores[m.record.id] = rrf_scores.get(m.record.id, 0) + 1 / (k + rank)
        if m.record.id not in record_map:
            record_map[m.record.id] = m

    if not rrf_scores:
        return []

    max_score = max(rrf_scores.values())
    sorted_ids = sorted(rrf_scores, key=lambda mid: rrf_scores[mid], reverse=True)

    result = []
    for mid in sorted_ids[:n]:
        normalized = rrf_scores[mid] / max_score if max_score > 0 else 0.5
        orig = record_map[mid]
        result.append(RecalledMemory(record=orig.record, similarity=normalized))

    return result
