from typing import Any

from dot_search.types import SearchResult


def reciprocal_rank_fusion(
    ranked_lists: list[list[SearchResult]],
    weights: list[float],
    k: int = 60,
) -> list[SearchResult]:
    scores: dict[str, float] = {}
    ids: dict[str, Any] = {}
    rows: dict[str, dict] = {}

    for ranked, weight in zip(ranked_lists, weights):
        for rank, result in enumerate(ranked):
            key = str(result.id)
            scores[key] = scores.get(key, 0.0) + weight / (k + rank + 1)
            ids[key] = result.id
            rows[key] = result.row

    sorted_keys = sorted(scores, key=lambda x: scores[x], reverse=True)
    return [
        SearchResult(id=ids[key], score=scores[key], row=rows[key])
        for key in sorted_keys
    ]
