"""
VYNDR Regime Detector
Detects material shifts in team-level metrics via PELT.
When detected: reset the 'recent' window for all players on the team.
Disabled when team has <20 games played.
"""

import logging
import numpy as np

logger = logging.getLogger('vyndr')

MIN_GAMES_FOR_DETECTION = 20
MONITORED_METRICS = ['pace', 'off_rating', 'three_rate', 'usage_entropy']


def detect_team_regime_change(team_games, lookback_games=20):
    """
    Detect material shifts in team-level metrics that indicate
    a regime change (coaching change, major trade, philosophy shift).

    Args:
        team_games: List of team game dicts with metric values.
            Each dict must have keys for at least some MONITORED_METRICS.
        lookback_games: Number of recent games to analyze.

    Returns:
        Dict with regime_change_detected (bool), and if detected:
        change_game_index, change_date, affected_metric, recommendation.
    """
    if not team_games or len(team_games) < MIN_GAMES_FOR_DETECTION:
        return {
            'regime_change_detected': False,
            'reason': 'insufficient_data',
            'games_available': len(team_games) if team_games else 0,
            'minimum_required': MIN_GAMES_FOR_DETECTION
        }

    games = team_games[-lookback_games:]

    for metric in MONITORED_METRICS:
        values = [g.get(metric) for g in games if g.get(metric) is not None]
        if len(values) < MIN_GAMES_FOR_DETECTION:
            continue

        changepoints = _detect_changepoints_simple(values)
        if changepoints:
            latest_cp = max(changepoints)
            # Only flag if the change is recent (last 5 games of the window)
            if latest_cp >= len(values) - 5:
                game_index = len(team_games) - len(games) + latest_cp
                return {
                    'regime_change_detected': True,
                    'change_game_index': latest_cp,
                    'change_date': games[latest_cp].get('game_date'),
                    'affected_metric': metric,
                    'recommendation': 'reset_recent_window_to_change_date'
                }

    return {'regime_change_detected': False}


def _detect_changepoints_simple(values, threshold=2.0):
    """
    Simple CUSUM-based changepoint detection.
    Used when full PELT is overkill for team-level detection.

    Args:
        values: List of numeric values.
        threshold: Z-score threshold for detecting a changepoint.

    Returns:
        List of changepoint indices.
    """
    if len(values) < 10:
        return []

    signal = np.array(values, dtype=float)
    overall_mean = np.mean(signal)
    overall_std = max(np.std(signal), 0.01)

    window = max(5, len(signal) // 4)
    changepoints = []

    for i in range(window, len(signal) - window + 1):
        left_mean = np.mean(signal[i - window:i])
        right_mean = np.mean(signal[i:i + window])
        diff = abs(right_mean - left_mean) / overall_std
        if diff > threshold:
            # Deduplicate: skip if too close to last detected
            if not changepoints or i - changepoints[-1] >= window:
                changepoints.append(i)

    return changepoints
