"""
VYNDR Unconventional Data Pipeline — Blueprint
Validates and applies unconventional factors (altitude, contract year, referee
crew history, travel distance, arena altitude) to prop adjustments.
Statistical validation via Pearson r with Bonferroni correction.
"""

import logging
from flask import Blueprint, request, jsonify
from scipy.stats import pearsonr

from utils.data_warehouse import get_factor_outcomes

logger = logging.getLogger(__name__)

unconventional_bp = Blueprint('unconventional', __name__)

# ---------------------------------------------------------------------------
# Validation thresholds
# ---------------------------------------------------------------------------
VALIDATION_REQUIREMENTS = {
    "min_historical_instances": 500,
    "min_pearson_r": 0.15,
    "max_p_value": 0.05,            # before Bonferroni
    "bonferroni_correction": True,
}

# ---------------------------------------------------------------------------
# Factor registry
# ---------------------------------------------------------------------------
UNCONVENTIONAL_FACTORS = {
    "altitude_adjustment": {
        "description": "Adjusts projections for games played at high altitude venues",
        "data_source": "venue_metadata",
        "affects": ["points", "rebounds", "total_bases"],
        "validated": False,
    },
    "contract_year": {
        "description": "Players in the final year of their contract tend to show elevated performance",
        "data_source": "contract_database",
        "affects": ["points", "rebounds", "assists"],
        "validated": False,
    },
    "referee_crew_history": {
        "description": "Historical tendencies of assigned referee crews on game totals and foul rates",
        "data_source": "referee_assignments",
        "affects": ["points", "rebounds"],
        "validated": False,
    },
    "travel_distance": {
        "description": "Fatigue signal derived from miles traveled in the preceding 48 hours",
        "data_source": "schedule_geodata",
        "affects": ["points", "rebounds", "assists"],
        "validated": True,
    },
    "arena_altitude": {
        "description": "Physiological impact of arena elevation on cardio-intensive stats",
        "data_source": "venue_metadata",
        "affects": ["points", "assists", "minutes"],
        "validated": False,
    },
}


# ---------------------------------------------------------------------------
# Core validation logic
# ---------------------------------------------------------------------------
def validate_unconventional_factor(factor_name, outcomes_data):
    """
    Run statistical validation on an unconventional factor.

    Requires at least 500 historical instances.  Computes Pearson r and
    applies Bonferroni correction across all currently-unvalidated factors.

    Args:
        factor_name: Key into UNCONVENTIONAL_FACTORS.
        outcomes_data: Dict with 'factor_values' and 'outcome_values' lists
                       of equal length.

    Returns:
        Dict with validation verdict and supporting statistics.
    """
    if factor_name not in UNCONVENTIONAL_FACTORS:
        return {"error": f"Unknown factor: {factor_name}"}

    factor_values = outcomes_data.get("factor_values", [])
    outcome_values = outcomes_data.get("outcome_values", [])

    sample_size = len(factor_values)
    min_instances = VALIDATION_REQUIREMENTS["min_historical_instances"]

    if sample_size < min_instances:
        return {
            "validated": False,
            "reason": f"Insufficient data: {sample_size} < {min_instances} required instances",
            "sample_size": sample_size,
        }

    # Pearson correlation
    r, p_value = pearsonr(factor_values, outcome_values)

    # Bonferroni correction — divide alpha by number of active (unvalidated) tests
    num_active_tests = sum(
        1 for f in UNCONVENTIONAL_FACTORS.values() if not f["validated"]
    )
    corrected_alpha = VALIDATION_REQUIREMENTS["max_p_value"] / max(num_active_tests, 1)

    passed = abs(r) >= VALIDATION_REQUIREMENTS["min_pearson_r"] and p_value < corrected_alpha

    if passed:
        UNCONVENTIONAL_FACTORS[factor_name]["validated"] = True
        logger.info(
            "Factor '%s' VALIDATED — r=%.4f, p=%.6f, alpha=%.6f, n=%d",
            factor_name, r, p_value, corrected_alpha, sample_size,
        )
    else:
        logger.info(
            "Factor '%s' FAILED validation — r=%.4f, p=%.6f, alpha=%.6f, n=%d",
            factor_name, r, p_value, corrected_alpha, sample_size,
        )

    return {
        "validated": passed,
        "pearson_r": round(r, 6),
        "p_value": round(p_value, 8),
        "corrected_alpha": round(corrected_alpha, 6),
        "sample_size": sample_size,
        "bonferroni_tests": num_active_tests,
    }


# ---------------------------------------------------------------------------
# Adjustment helper
# ---------------------------------------------------------------------------
def _get_adjustment_value(factor_name, player_id):
    """
    Compute the adjustment value for a validated factor and player.

    Returns 0.0 when the factor is not yet validated.
    """
    factor = UNCONVENTIONAL_FACTORS.get(factor_name)
    if not factor or not factor["validated"]:
        return 0.0

    outcomes = get_factor_outcomes(factor_name, player_id)
    if not outcomes or not outcomes.get("adjustment"):
        return 0.0

    return outcomes["adjustment"]


# ---------------------------------------------------------------------------
# Endpoints
# ---------------------------------------------------------------------------
@unconventional_bp.route("/validate/<factor_name>", methods=["POST"])
def validate_factor(factor_name):
    """Manually trigger validation for a single unconventional factor."""
    if factor_name not in UNCONVENTIONAL_FACTORS:
        return jsonify({"error": f"Unknown factor: {factor_name}"}), 404

    try:
        outcomes_data = get_factor_outcomes(factor_name)
        result = validate_unconventional_factor(factor_name, outcomes_data)
        return jsonify(result), 200
    except Exception as exc:
        logger.exception("Validation failed for factor '%s'", factor_name)
        return jsonify({"error": str(exc)}), 500


@unconventional_bp.route("/status", methods=["GET"])
def factor_status():
    """Return all unconventional factors with their current validation state."""
    return jsonify(UNCONVENTIONAL_FACTORS), 200


@unconventional_bp.route("/adjustment/<factor_name>/<player_id>", methods=["GET"])
def get_adjustment(factor_name, player_id):
    """
    Get the prop adjustment value for a validated factor and player.

    Returns 0.0 if the factor has not been validated.
    """
    if factor_name not in UNCONVENTIONAL_FACTORS:
        return jsonify({"error": f"Unknown factor: {factor_name}"}), 404

    adjustment = _get_adjustment_value(factor_name, player_id)
    factor = UNCONVENTIONAL_FACTORS[factor_name]

    return jsonify({
        "factor": factor_name,
        "player_id": player_id,
        "adjustment": adjustment,
        "validated": factor["validated"],
        "affects": factor["affects"],
    }), 200


# ---------------------------------------------------------------------------
# PATCH Item 9: Daily data collection + monthly validation
# ---------------------------------------------------------------------------

def collect_daily_factor_data(game_date):
    """
    Collect unconventional factor data points alongside regular game data.
    Called by nightly resolution step 17. Accumulates so monthly validation
    has something to validate against.

    Args:
        game_date: Date string (YYYY-MM-DD).
    """
    logger.info(f'[VYNDR] Collecting unconventional factor data for {game_date}')
    # In production: iterate completed games, check each factor
    # For altitude: log games at venues > 3000ft
    # For contract year: check player contract status
    # For referee crew: log crew assignments
    # Store via log_factor_data


def log_factor_data(factor_name, game_id, game_date, extra_data):
    """
    Store a data point for future validation.

    Args:
        factor_name: Factor identifier string.
        game_id: Game identifier.
        game_date: Date string.
        extra_data: Dict of factor-specific data.
    """
    try:
        import json
        from utils.supabase_client import get_supabase_client
        supabase = get_supabase_client()
        if supabase:
            supabase.table('unconventional_factor_data').insert({
                'factor_name': factor_name,
                'game_id': game_id,
                'game_date': game_date,
                'factor_value': json.dumps(extra_data),
            }).execute()
    except Exception as e:
        logger.warning(f'[VYNDR] Factor data log failed: {e}')


def run_monthly_validation():
    """
    Run validation on all unvalidated factors. Called on 1st of each month
    by nightly resolution step 18.
    """
    logger.info('[VYNDR] Running monthly unconventional factor validation')
    for factor_name, factor in UNCONVENTIONAL_FACTORS.items():
        if factor['validated']:
            continue
        logger.info(f'[VYNDR] Validating {factor_name}...')
        # In production: fetch outcomes from unconventional_factor_data
        # and run validate_unconventional_factor
