"""
VYNDR Sportsbook Deep Links + Parlay Builder
10 books. Deep link to game/player page. Parlay grading with correlation check.
"""

import logging

logger = logging.getLogger('vyndr')

SPORTSBOOKS = {
    'draftkings': {
        'name': 'DraftKings',
        'base_url': 'https://sportsbook.draftkings.com',
        'deep_link_pattern': '/event/{event_id}'
    },
    'fanduel': {
        'name': 'FanDuel',
        'base_url': 'https://sportsbook.fanduel.com',
        'deep_link_pattern': '/sport/{sport}/event/{event_id}'
    },
    'betmgm': {
        'name': 'BetMGM',
        'base_url': 'https://sports.betmgm.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'caesars': {
        'name': 'Caesars',
        'base_url': 'https://www.caesars.com/sportsbook-and-casino',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'bet365': {
        'name': 'bet365',
        'base_url': 'https://www.bet365.com',
        'deep_link_pattern': '/#/AC/B{sport_id}/C{event_id}'
    },
    'pointsbet': {
        'name': 'PointsBet',
        'base_url': 'https://pointsbet.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'betrivers': {
        'name': 'BetRivers',
        'base_url': 'https://www.betrivers.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'fanatics': {
        'name': 'Fanatics',
        'base_url': 'https://sportsbook.fanatics.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'hardrockbet': {
        'name': 'Hard Rock Bet',
        'base_url': 'https://app.hardrockbet.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    },
    'espnbet': {
        'name': 'ESPN BET',
        'base_url': 'https://espnbet.com',
        'deep_link_pattern': '/sports/{sport}/event/{event_id}'
    }
}


def grade_parlay(legs, grade_fn):
    """
    Grade a parlay: grade each leg, compound probability, apply penalty.
    Parlay grade = average leg confidence minus penalty per leg after 2.

    Args:
        legs: List of leg dicts with grading params.
        grade_fn: Function to grade a single leg.

    Returns:
        Dict with parlay_grade, compound_probability, individual grades, warnings.
    """
    graded_legs = []
    compound_prob = 1.0

    for leg in legs:
        result = grade_fn(leg)
        graded_legs.append(result)
        compound_prob *= result.get('confidence', 0.5)

    if not graded_legs:
        return {'error': 'No legs to grade'}

    # Average confidence
    avg_confidence = sum(l.get('confidence', 0.5) for l in graded_legs) / len(graded_legs)

    # Penalty per leg after 2 (each extra leg subtracts 0.03)
    leg_penalty = max(0, len(graded_legs) - 2) * 0.03
    parlay_confidence = max(0.0, avg_confidence - leg_penalty)

    # Warning on 4+ legs
    warnings = []
    if len(graded_legs) >= 4:
        warnings.append({
            'type': 'leg_count',
            'message': f'{len(graded_legs)} legs — compound probability is {compound_prob:.4f}. '
                       'Sportsbooks profit most from large parlays.'
        })

    # Correlation check
    correlation_warnings = check_parlay_correlation(graded_legs)
    warnings.extend(correlation_warnings)

    return {
        'parlay_confidence': round(parlay_confidence, 3),
        'compound_probability': round(compound_prob, 6),
        'leg_count': len(graded_legs),
        'leg_penalty': round(leg_penalty, 3),
        'legs': graded_legs,
        'warnings': warnings
    }


def check_parlay_correlation(legs):
    """
    Check for correlated legs in a parlay.
    Same-game detection is free. Structural correlation applies immediately.
    Statistical correlation (phi) needs 30+ joint outcomes.

    Args:
        legs: List of graded leg dicts with game_id, team, player_id, stat_type.

    Returns:
        List of correlation warning dicts.
    """
    warnings = []

    # Group by game
    game_groups = {}
    for i, leg in enumerate(legs):
        gid = leg.get('game_id', f'unknown_{i}')
        game_groups.setdefault(gid, []).append(leg)

    for game_id, game_legs in game_groups.items():
        if len(game_legs) < 2:
            continue

        warnings.append({
            'type': 'same_game',
            'game_id': game_id,
            'legs_affected': len(game_legs),
            'message': f'{len(game_legs)} legs from the same game — correlation risk'
        })

        # Structural correlation: same team
        team_groups = {}
        for leg in game_legs:
            team = leg.get('team', 'unknown')
            team_groups.setdefault(team, []).append(leg)

        for team, team_legs in team_groups.items():
            if len(team_legs) >= 2:
                penalty = 0.03 * (len(team_legs) - 1)
                warnings.append({
                    'type': 'structural_correlation',
                    'team': team,
                    'penalty': penalty,
                    'message': f'{len(team_legs)} props on same team — '
                               f'{penalty * 100:.0f}% confidence reduction'
                })

    return warnings


def get_phi_coefficient(player_a_id, player_b_id, stat_a, stat_b, joint_outcomes=None):
    """
    Calculate phi coefficient from joint outcomes.
    Requires minimum 30 joint instances before reporting.

    Args:
        player_a_id: First player ID.
        player_b_id: Second player ID.
        stat_a: First stat type.
        stat_b: Second stat type.
        joint_outcomes: Optional list of joint outcome dicts.

    Returns:
        Float phi coefficient, or None if insufficient data.
    """
    if not joint_outcomes or len(joint_outcomes) < 30:
        return None

    # 2x2 contingency table
    a = sum(1 for j in joint_outcomes if j['hit_a'] and j['hit_b'])
    b = sum(1 for j in joint_outcomes if j['hit_a'] and not j['hit_b'])
    c = sum(1 for j in joint_outcomes if not j['hit_a'] and j['hit_b'])
    d = sum(1 for j in joint_outcomes if not j['hit_a'] and not j['hit_b'])

    n = a + b + c + d
    if n == 0:
        return None

    denom = ((a + b) * (c + d) * (a + c) * (b + d)) ** 0.5
    if denom == 0:
        return None

    phi = (a * d - b * c) / denom
    return round(phi, 3)
