
from fantasy_data.services import load_team_upcoming_fix_difficulty_data
from typing import Any, Dict
import pandas as pd
from fantasy_data.services import load_players_data,load_team_upcoming_fix_difficulty_data

difficulty_multiplier = {
    1: 1.2,  # easiest
    2: 1.1,
    3: 1.0,  # neutral
    4: 0.9,
    5: 0.8   # hardest
}


def calculate_player_expected_score2(player):
  """Calculates expected points based on various factors."""

  # Get the player's team

  # Find the fixture difficulty for the player's team
  fixture_difficulty =  get_current_gw_opponent_diffuclty(player['team']) # Default to neutral if team not found
  ict_index  = float (player["ict_index"])/ 100.0
  form = float(player["form"] )/ 10.0  
  # Use the difficulty multiplier based on the fixture difficulty
  if fixture_difficulty in difficulty_multiplier:
    difficulty_factor = difficulty_multiplier[fixture_difficulty]
  else:
    difficulty_factor = 1.0  # Default to neutral if difficulty not found

  # Positional Points
  if player['element_type'] == "GK":  # Goalkeeper
    goal_points = 6
    assist_points = 3
    clean_sheet_points = 4
  elif player['element_type'] == "DEF":  # Defender
    goal_points = 6
    assist_points = 3
    clean_sheet_points = 4
  elif player['element_type'] == "MID":  # Midfielder
    goal_points = 5
    assist_points = 3
    clean_sheet_points = 1
  elif player['element_type'] == "FWD":  # Forward
    goal_points = 4
    assist_points = 3
    clean_sheet_points = 0
  else:
    goal_points = 0
    assist_points = 0
    clean_sheet_points = 0

  # Calculate games played (approximation) only if minutes are above a threshold
  min_minutes = 200 # Example threshold - adjust as needed
  if player['minutes'] > 1:
    games_played = player['minutes'] / 90
  else:
    games_played = 1  # Avoid division by zero and prevent skewing

  # Expected Points based on Goals, Assists, Clean Sheets, etc.

  expected_points = (
      (player['goals_scored'] / games_played) * goal_points +
      (player['assists'] / games_played) * assist_points +
      (player['clean_sheets'] / games_played) * clean_sheet_points    # Basic playing time contribution
  )

  # Adjust for fixture difficulty
  expected_points = expected_points * (difficulty_factor *( 0.5 + form + (0.05 * ict_index) )) + 2

  return expected_points

def calculate_player_expected_score(
    player: Dict[str, Any],pos:str,
) :
    goal_points = 4 if pos == 'FWD' else 5 if pos == 'MID' else 6 
    assist_points = 3
    playing_points = 2
    clean_sheet_points = 4 if pos in ('DEF', 'GK') else 1 if pos =="MID" else 0
    goals_conceded_penalty = -0.5 if pos in ('DEF', 'GK') else 0

    xgc_per_90 = player["expected_goals_conceded_per_90"]
    xg_per_90 = player["expected_goals_per_90"]
    xa_per_90 = player["expected_assists_per_90"]
    ict_index  = float (player["ict_index"])/ 100.0
    form = float(player["form"] )/ 10.0  # Scale form to 0-1
    match_difficulty =  calculate_match_difficulty_impact( get_current_gw_opponent_diffuclty(player['team']))
    expected_goals = (xg_per_90 * match_difficulty * 1.75) * (0.5 + form + (0.05 * ict_index))
    expected_assists = (xa_per_90  * match_difficulty  * 2.25) * (0.5 + form  +  (0.065 * ict_index) )
    expected_goal_points = expected_goals * goal_points 
    expected_assist_points = expected_assists * assist_points

    expected_clean_sheet_probability =0
    expected_goals_conceded = 0
    
    if pos in ('DEF', 'GK'):
        if pos == "GK":
            expected_clean_sheet_probability = 1 - ( (0.1 / match_difficulty)  +  (0.5*form))
        else :
            expected_clean_sheet_probability = 1 - ( (0.085 / match_difficulty)  +  (0.25*form))
        expected_goals_conceded = xgc_per_90 * (1 / match_difficulty)* (60/90) 
        
    expected_clean_sheet_points = expected_clean_sheet_probability * clean_sheet_points
    expected_goals_conceded_points =  expected_goals_conceded * goals_conceded_penalty # No positive deduction
    total_expected_points = round (expected_goal_points + expected_assist_points +
                            expected_clean_sheet_points + expected_goals_conceded_points + playing_points , 1 )


    return max(0, total_expected_points)

def calculate_match_difficulty_impact(diff : int)-> float:
    if diff == 0:
        return 0
    elif diff == 1:
        return 1.35
    else:
        # You can adjust the scaling factor (e.g., the exponent) to control the rate of decrease.
        # A value slightly less than 1 will make the decrease gradual.
        scaling_factor = 0.8
        return scaling_factor ** (diff - 1)
    
def get_current_gw_opponent_diffuclty(team_id:int)-> int:
    team_fix = load_team_upcoming_fix_difficulty_data()
    return team_fix[team_id - 1]["GW_1"]
