"""Cross-source merging and scoring for trending topics."""

from typing import List, Dict

from config import MAX_ITEMS_PER_SOURCE, CROSS_SOURCE_BOOST, MIN_SOURCES_FOR_BOOST
from .deduplicator import deduplicate_topics


def normalize_score(rank: int, max_rank: int = MAX_ITEMS_PER_SOURCE) -> float:
    """
    Convert rank to a 0-1 score (higher = better).

    Args:
        rank: Position in source list (1 = best)
        max_rank: Maximum possible rank

    Returns:
        Normalized score between 0 and 1
    """
    return 1.0 - ((rank - 1) / max_rank)


def merge_and_score(items: List[dict]) -> List[dict]:
    """
    Merge items from all sources with equal weighting and cross-source boosting.

    1. Normalize ranks to 0-1 scores per source
    2. Deduplicate with fuzzy matching
    3. Apply cross-source boost for topics in 2+ sources
    4. Sort by final score

    Args:
        items: List of trend item dictionaries from all sources

    Returns:
        Merged, deduplicated, and scored list
    """
    if not items:
        return []

    # Step 1: Add normalized scores
    for item in items:
        item["normalized_score"] = normalize_score(item["rank"])

    # Step 2: Deduplicate
    deduped = deduplicate_topics(items)

    # Step 3: Calculate final scores with cross-source boost
    for item in deduped:
        base_score = item["normalized_score"]
        source_count = item.get("source_count", 1)

        # Apply boost for topics appearing in multiple sources
        if source_count >= MIN_SOURCES_FOR_BOOST:
            item["final_score"] = base_score * CROSS_SOURCE_BOOST
            item["boosted"] = True
        else:
            item["final_score"] = base_score
            item["boosted"] = False

    # Step 4: Sort by final score (descending)
    deduped.sort(key=lambda x: x["final_score"], reverse=True)

    # Assign final ranks
    for i, item in enumerate(deduped, start=1):
        item["final_rank"] = i

    return deduped


def merge_by_region(all_items: List[dict]) -> Dict[str, List[dict]]:
    """
    Merge items grouped by region.

    Args:
        all_items: List of all trend items from all sources and regions

    Returns:
        Dictionary mapping region to merged/scored trend list
    """
    by_region: Dict[str, List[dict]] = {}

    # Group by region
    for item in all_items:
        region = item["region"]
        if region not in by_region:
            by_region[region] = []
        by_region[region].append(item)

    # Merge each region
    return {region: merge_and_score(items) for region, items in by_region.items()}


def merge_all_regions(all_items: List[dict]) -> List[dict]:
    """
    Merge all items across all regions into a single list.

    Useful for seeing overall trending topics regardless of region.

    Args:
        all_items: List of all trend items from all sources and regions

    Returns:
        Single merged/scored trend list
    """
    return merge_and_score(all_items)
