import pandas as pd
import numpy as np
import os

seasons = ['1920','2021','2122','2223','2324','2425','2526']
league_names = {
    'E0':'EPL','E1':'Championship','E2':'League One','E3':'League Two','EC':'Conference',
    'SP1':'La Liga','SP2':'Segunda','I1':'Serie A','I2':'Serie B',
    'D1':'Bundesliga','D2':'2.Bundesliga','F1':'Ligue 1','F2':'Ligue 2',
    'N1':'Eredivisie','B1':'Belgian Pro League','P1':'Primeira Liga',
    'T1':'Super Lig','G1':'Greek SL',
    'SC0':'Scottish Prem','SC1':'Scottish Champ','SC2':'Scottish L1','SC3':'Scottish L2',
}

def simulate(bets):
    if not bets: return 0,0.0,0.0,0.0
    profits = [(o-1) if w else -1 for o,w in bets]
    n = len(profits); total = sum(profits)
    return n, round(total,2), round(total/n*100,2), round(sum(w for _,w in bets)/n*100,1)

def remove_margin(h,d,a):
    over = 1/h+1/d+1/a
    return 1/h/over, 1/d/over, 1/a/over

# Load all data
all_dfs = []
for code, name in league_names.items():
    for s in seasons:
        path = f'E:/soccer/league_data/{code}_{s}.csv'
        try:
            d = pd.read_csv(path, encoding='utf-8-sig')
            if len(d) < 10 or 'FTR' not in d.columns or 'B365A' not in d.columns: continue
            d = d.dropna(subset=['FTR','B365A','PSCH','PSCD','PSCA'])
            if len(d) < 10: continue
            d['Season'] = s; d['LeagueName'] = name
            all_dfs.append(d)
        except: pass

df = pd.concat(all_dfs, ignore_index=True)
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True, errors='coerce')
df = df.dropna(subset=['Date']).sort_values('Date').reset_index(drop=True)

tH,tD,tA = zip(*df.apply(lambda r: remove_margin(r['PSCH'],r['PSCD'],r['PSCA']), axis=1))
df = df.copy()
df['PSC_fair_H'] = 1/pd.Series(tH,index=df.index)
df['PSC_fair_D'] = 1/pd.Series(tD,index=df.index)
df['PSC_fair_A'] = 1/pd.Series(tA,index=df.index)
df['edge_A'] = (df['B365A']-df['PSC_fair_A'])/df['PSC_fair_A']
df['edge_H'] = (df['B365H']-df['PSC_fair_H'])/df['PSC_fair_H']
df['edge_D'] = (df['B365D']-df['PSC_fair_D'])/df['PSC_fair_D']

# Build best-outcome bets per league (same as before)
best_config = {
    '2.Bundesliga':   ('Home','edge_H','B365H','H'),
    'Belgian Pro League': ('Away','edge_A','B365A','A'),
    'Bundesliga':     ('Home','edge_H','B365H','H'),
    'Championship':   ('Draw','edge_D','B365D','D'),
    'Conference':     ('Home','edge_H','B365H','H'),
    'EPL':            ('Away','edge_A','B365A','A'),
    'Eredivisie':     ('Home','edge_H','B365H','H'),
    'Greek SL':       ('Draw','edge_D','B365D','D'),
    'La Liga':        ('Home','edge_H','B365H','H'),
    'League One':     ('Home','edge_H','B365H','H'),
    'League Two':     ('Home','edge_H','B365H','H'),
    'Ligue 1':        ('Away','edge_A','B365A','A'),
    'Ligue 2':        ('Home','edge_H','B365H','H'),
    'Primeira Liga':  ('Away','edge_A','B365A','A'),
    'Scottish Champ': ('Draw','edge_D','B365D','D'),
    'Scottish L1':    ('Away','edge_A','B365A','A'),
    'Scottish L2':    ('Draw','edge_D','B365D','D'),
    'Scottish Prem':  ('Home','edge_H','B365H','H'),
    'Segunda':        ('Home','edge_H','B365H','H'),
    'Serie A':        ('Draw','edge_D','B365D','D'),
    'Serie B':        ('Home','edge_H','B365H','H'),
    'Super Lig':      ('Draw','edge_D','B365D','D'),
}

rows = []
for name, (outcome, edge_col, odds_col, result) in best_config.items():
    sub = df[(df['LeagueName']==name) & (df[edge_col]>0.05)]
    for _, r in sub.iterrows():
        tH2,tD2,tA2 = remove_margin(r['PSCH'],r['PSCD'],r['PSCA'])
        p = {'H':tH2,'D':tD2,'A':tA2}[result]
        b = r[odds_col]-1
        edge = r[odds_col]*p-1
        kelly_f = edge/b if b>0 else 0
        if kelly_f > 0:
            rows.append({'Date':r['Date'],'Season':r['Season'],'League':name,
                         'Outcome':outcome,'Odds':r[odds_col],'Kelly':kelly_f,
                         'Won':r['FTR']==result})

bets_df = pd.DataFrame(rows).sort_values('Date').reset_index(drop=True)
bets_df['Week'] = bets_df['Date'].dt.to_period('W')

# ---------------------------------------------------------------
# SEASON-BY-SEASON: continuous bankroll
# ---------------------------------------------------------------
KELLY_MULT = 0.25
bankroll = 1000.0
season_snapshots = {}
season_start_br = {}
week_history = []

for week, grp in bets_df.groupby('Week'):
    season = grp['Season'].mode()[0]
    if season not in season_start_br:
        season_start_br[season] = bankroll

    wpl = 0; wins = 0; staked = 0
    for _, bet in grp.iterrows():
        f = min(bet['Kelly']*KELLY_MULT, 0.25)
        stake = bankroll*f
        staked += stake
        if bet['Won']:
            wpl += stake*(bet['Odds']-1); wins += 1
        else:
            wpl -= stake
    bankroll += wpl
    week_history.append({'Week':str(week),'Season':season,'N':len(grp),
                         'Wins':wins,'PL':wpl,'Bankroll':bankroll})

# End-of-season bankroll = last week of each season
hist_df = pd.DataFrame(week_history)
for s in seasons:
    sub = hist_df[hist_df['Season']==s]
    if not sub.empty:
        season_snapshots[s] = sub['Bankroll'].iloc[-1]

# ---------------------------------------------------------------
# PRINT: season by season
# ---------------------------------------------------------------
print("="*80)
print("SEASON-BY-SEASON RETURNS — Best CLV outcome per league, 0.25x Kelly")
print("Continuous bankroll (not reset each season)")
print("="*80)
print(f"\n{'Season':<10} {'Start £':>12} {'End £':>14} {'Return':>8} {'Bets':>6} {'WR%':>6} {'Max DD%':>9}")
print("-"*80)

prev_br = 1000.0
for s in seasons:
    sub_bets = bets_df[bets_df['Season']==s]
    sub_hist = hist_df[hist_df['Season']==s]
    if sub_hist.empty: continue

    start_br = season_start_br.get(s, prev_br)
    end_br = season_snapshots.get(s, prev_br)
    ret_pct = (end_br/start_br - 1)*100
    n_bets = len(sub_bets)
    wr = sub_bets['Won'].mean()*100 if n_bets>0 else 0

    # Max drawdown within season
    br_series = sub_hist['Bankroll']
    peak = br_series.cummax()
    dd = ((peak - br_series)/peak*100).max()

    marker = " +" if ret_pct > 0 else " --"
    print(f"{s:<10} £{start_br:>11,.2f} £{end_br:>13,.2f} {ret_pct:>+7.1f}%{marker}  {n_bets:>5}  {wr:>5.1f}%  {dd:>7.1f}%")
    prev_br = end_br

print(f"\n{'TOTAL':<10} £{'1,000.00':>11} £{prev_br:>13,.2f} {(prev_br/1000-1)*100:>+7.1f}%")

# ---------------------------------------------------------------
# ALSO: flat £1/unit per bet for comparison (no compounding)
# ---------------------------------------------------------------
print("\n" + "="*80)
print("FLAT BETTING (£1/unit per bet) — season by season, no compounding")
print("="*80)
print(f"\n{'Season':<10} {'Bets':>5}  {'P&L':>8}  {'ROI%':>7}  {'WR%':>6}")
print("-"*80)
total_bets=[]; total_pl=0
for s in seasons:
    sub = bets_df[bets_df['Season']==s]
    bets = [(r['Odds'], r['Won']) for _,r in sub.iterrows()]
    n,p,roi,wr = simulate(bets)
    marker = " +" if roi>0 else ""
    print(f"{s:<10} {n:>5}  {p:>8.2f}  {roi:>7.2f}%  {wr:>5.1f}%{marker}")
    total_pl += p; total_bets.extend(bets)

n_all,p_all,roi_all,wr_all = simulate(total_bets)
print(f"{'ALL':<10} {n_all:>5}  {p_all:>8.2f}  {roi_all:>7.2f}%  {wr_all:>5.1f}%")

# ---------------------------------------------------------------
# PER-LEAGUE per-season heatmap (flat ROI)
# ---------------------------------------------------------------
print("\n" + "="*95)
print("PER-LEAGUE PER-SEASON ROI% (flat betting, best outcome per league, >5% edge)")
print("="*95)
header = f"{'League':<22}" + "".join(f"  {s:>8}" for s in seasons) + f"  {'ALL':>8}"
print(header)
print("-"*95)
for name, (outcome, edge_col, odds_col, result) in sorted(best_config.items()):
    row_str = f"{name:<22}"
    all_bets = []
    for s in seasons:
        sub = bets_df[(bets_df['League']==name)&(bets_df['Season']==s)]
        bets = [(r['Odds'],r['Won']) for _,r in sub.iterrows()]
        n,p,roi,wr = simulate(bets)
        all_bets.extend(bets)
        if n >= 5:
            row_str += f"  {roi:>+7.1f}%"
        else:
            row_str += f"  {'n/a':>8}"
    n,p,roi,wr = simulate(all_bets)
    row_str += f"  {roi:>+7.1f}%"
    print(row_str)
