"""Weighted fuzzy search helpers for TUI pickers."""

from __future__ import annotations

import difflib
from dataclasses import dataclass


@dataclass(slots=True, frozen=True)
class FuzzyCandidate:
    """Result candidate with score metadata."""

    value: str
    score: float
    reason: str


def score_match(query: str, value: str) -> FuzzyCandidate | None:
    """Score a query against value using ADR-aligned weighting."""
    if not query:
        return FuzzyCandidate(value=value, score=0.0, reason="empty")
    if value.startswith(query):
        return FuzzyCandidate(value=value, score=1.0, reason="prefix")
    if query in value:
        return FuzzyCandidate(value=value, score=0.7, reason="substring")
    query_parts = [part for part in query.split("/") if part]
    if query_parts and all(part in value for part in query_parts):
        return FuzzyCandidate(value=value, score=0.8, reason="path-component")
    ratio = difflib.SequenceMatcher(a=query, b=value).ratio()
    if ratio >= 0.4:
        return FuzzyCandidate(value=value, score=0.4 * ratio, reason="fuzzy")
    return None


def rank_candidates(
    query: str,
    values: list[str],
    *,
    recency: dict[str, int] | None = None,
    limit: int = 20,
) -> list[FuzzyCandidate]:
    """Return ranked fuzzy candidates with deterministic tie-breaking."""
    scored: list[FuzzyCandidate] = []
    for value in values:
        candidate = score_match(query, value)
        if candidate is not None:
            scored.append(candidate)

    recency_map = recency or {}
    scored.sort(
        key=lambda item: (
            -item.score,
            -recency_map.get(item.value, 0),
            item.value,
        )
    )
    return scored[:limit]
