"""
Reconciliation: cross-check player-team mappings across sources.

Detects:
- Player on wrong team (trade not reflected)
- Identity collisions (duplicate names)
- Market/official mismatches
"""

import logging
from typing import List, Dict, Any, Optional, Tuple

from .normalization import canonicalize_team_identifier, normalize_player_name
from .models import ConflictDetail

log = logging.getLogger("pub-integrity")


def reconcile_player_team(
    player_name: str,
    prop_team: str,
    roster_entries: List[Dict[str, Any]],
    market_props: List[Dict[str, Any]],
    league: Optional[str] = None,
) -> Tuple[bool, Optional[ConflictDetail]]:
    """
    Verify that a player is mapped to the correct team.

    Returns (is_valid, conflict_or_none).
    """
    norm_name = normalize_player_name(player_name)
    norm_team = canonicalize_team_identifier(prop_team, league)

    # Find this player in roster data
    roster_team = None
    for entry in roster_entries:
        if entry.get("normalized_name") == norm_name:
            roster_team = canonicalize_team_identifier(entry.get("team", ""), league)
            break

    # If player not found in roster at all — uncertain, flag for review
    if roster_team is None:
        return True, None  # Can't validate — don't block on missing roster data

    # Check team match
    if roster_team and norm_team and roster_team != norm_team:
        conflict = ConflictDetail(
            conflict_type="TEAM_MISMATCH",
            player_name=player_name,
            player_id=norm_name,
            field="current_team",
            official_value=roster_team,
            internal_value=norm_team,
            severity="high",
            source="roster_reconciliation",
            detail=f"Player {player_name} is on {roster_team} per roster data, "
                   f"but prop assigns them to {norm_team}",
        )
        log.warning(f"[reconcile] Team mismatch: {player_name} roster={roster_team} prop={norm_team}")
        return False, conflict

    # Check market presence for cross-validation
    market_team = None
    for mp in market_props:
        if mp.get("normalized_name") == norm_name:
            market_team = canonicalize_team_identifier(mp.get("team", ""), league)
            break

    if market_team and norm_team and market_team != norm_team:
        conflict = ConflictDetail(
            conflict_type="MARKET_TEAM_MISMATCH",
            player_name=player_name,
            player_id=norm_name,
            field="market_team",
            official_value=roster_team or "unknown",
            market_value=market_team,
            internal_value=norm_team,
            severity="medium",
            source="market_reconciliation",
            detail=f"Market has {player_name} on {market_team}, prop has {norm_team}",
        )
        log.warning(f"[reconcile] Market team mismatch: {player_name} market={market_team} prop={norm_team}")
        return False, conflict

    return True, None


def detect_identity_collisions(
    roster_entries: List[Dict[str, Any]],
    league: str,
) -> List[ConflictDetail]:
    """Detect players with same normalized name on different teams (same league)."""
    name_teams: Dict[str, List[str]] = {}
    for entry in roster_entries:
        norm = entry.get("normalized_name", "")
        team = canonicalize_team_identifier(entry.get("team", ""), league)
        if norm and team:
            name_teams.setdefault(norm, []).append(team)

    conflicts = []
    for norm_name, teams in name_teams.items():
        unique_teams = list(set(teams))
        if len(unique_teams) > 1:
            conflicts.append(ConflictDetail(
                conflict_type="IDENTITY_COLLISION",
                player_name=norm_name,
                player_id=norm_name,
                field="team_assignment",
                internal_value=", ".join(unique_teams),
                severity="high",
                source="identity_collision_check",
                detail=f"Player '{norm_name}' appears on multiple teams: {unique_teams}",
            ))
            log.warning(f"[reconcile] Identity collision: '{norm_name}' on teams {unique_teams}")

    return conflicts


def detect_stale_mappings(
    forecast_props: List[Dict[str, Any]],
    roster_entries: List[Dict[str, Any]],
) -> List[ConflictDetail]:
    """Detect forecast props referencing players not found in recent roster data."""
    roster_names = {e.get("normalized_name") for e in roster_entries if e.get("normalized_name")}

    conflicts = []
    for prop in forecast_props:
        norm = prop.get("normalized_name", "")
        if norm and norm not in roster_names:
            conflicts.append(ConflictDetail(
                conflict_type="STALE_MAPPING",
                player_name=prop.get("player_name", norm),
                player_id=norm,
                field="roster_presence",
                internal_value=prop.get("event_id", ""),
                severity="medium",
                source="stale_mapping_check",
                detail=f"Player '{prop.get('player_name', norm)}' in forecast but not in recent roster data",
            ))

    if conflicts:
        log.warning(f"[reconcile] {len(conflicts)} stale mapping(s) detected")
    return conflicts
