"""
Rebuild Kalshi entries in bet_history.
Rules:
  - YES bets: CLV > threshold, Kelly at ask, floor $1
  - NO bets:  when YES raw Kelly < $1, ALSO compute opponent NO Kelly
              (Away YES -> Home NO,  Home YES -> Away NO)
              Place NO bet if Kelly > 0, floor $1
"""
import json, csv
from pathlib import Path

BET_HISTORY = Path(r'E:\soccer\bet_history.json')
LIVE_DATA   = Path(r'E:\soccer\live_data')
KALSHI_BR   = Path(r'E:\soccer\kalshi_bankroll.json')

EDGE_AWAY = 0.05
EDGE_HOME = 0.08
MIN_STAKE = 1.00

def kelly_raw(p, ask):
    if ask <= 0 or ask >= 1 or p <= 0:
        return 0.0
    b = (1 - ask) / ask
    f = (p * b - (1 - p)) / b
    return max(f, 0.0)

def kelly_stake(p, ask, bankroll):
    f = kelly_raw(p, ask)
    if f <= 0:
        return 0.0
    return max(bankroll * f * 0.25, MIN_STAKE)

def calc_pnl(stake, ask, won):
    if won is True:
        return round(stake * (1.0/ask - 1.0), 2)
    elif won is False:
        return -round(stake, 2)
    return 0.0

# Build lookup from first PRE snapshot where CLV > threshold
lookup = {}
for csv_file in sorted(LIVE_DATA.glob('*.csv')):
    date = csv_file.stem
    seen = set()
    with open(csv_file, newline='', encoding='utf-8') as fh:
        for row in csv.DictReader(fh):
            if row.get('status','') not in ('PRE',''):
                continue
            home = row['home'].lower().strip()
            away = row['away'].lower().strip()

            def fv(col):
                try: return float(row.get(col) or 0)
                except: return 0.0

            ftr     = row.get('ftr','')
            score_h = row.get('result_home','')
            score_a = row.get('result_away','')

            # Away YES side
            clv_a = fv('clv_kalshi_away')
            ask_a = fv('kalshi_away_ask')
            pf_a  = fv('pin_fair_away')
            bid_h = fv('kalshi_home_bid')
            pf_h  = fv('pin_fair_home')
            key_a = (date, home, away, 'away')
            if key_a not in seen and clv_a >= EDGE_AWAY and ask_a > 0 and pf_a > 0:
                lookup[key_a] = {
                    'ask': ask_a, 'pin_fair': pf_a, 'clv': clv_a,
                    'opp_bid': bid_h, 'opp_pin_fair': pf_h,
                    'ftr': ftr, 'score_h': score_h, 'score_a': score_a,
                }
                seen.add(key_a)

            # Home YES side
            clv_h  = fv('clv_kalshi_home')
            ask_h  = fv('kalshi_home_ask')
            pf_h2  = fv('pin_fair_home')
            bid_a  = fv('kalshi_away_bid')
            pf_a2  = fv('pin_fair_away')
            key_h = (date, home, away, 'home')
            if key_h not in seen and clv_h >= EDGE_HOME and ask_h > 0 and pf_h2 > 0:
                lookup[key_h] = {
                    'ask': ask_h, 'pin_fair': pf_h2, 'clv': clv_h,
                    'opp_bid': bid_a, 'opp_pin_fair': pf_a2,
                    'ftr': ftr, 'score_h': score_h, 'score_a': score_a,
                }
                seen.add(key_h)

print(f"Lookup entries: {len(lookup)}")

bets = json.loads(BET_HISTORY.read_text())
kalshi_br = 1000.0
new_bets = []
no_bets_added = 0

for b in bets:
    date  = b.get('date','')
    home  = b.get('home','')
    away  = b.get('away','')
    side  = b.get('bet','').lower().strip()
    homel = home.lower().strip()
    awayl = away.lower().strip()

    key = (date, homel, awayl, side)
    has_kalshi = bool(b.get('kalshi_ask') or b.get('kalshi_stake'))
    in_lookup  = key in lookup

    if not has_kalshi and not in_lookup:
        new_bets.append(b)
        continue

    if not in_lookup:
        for k in ['kalshi_ask','kalshi_stake','kalshi_pnl','kalshi_bankroll_after']:
            b.pop(k, None)
        new_bets.append(b)
        continue

    info  = lookup[key]
    ask   = info['ask']
    pf    = info['pin_fair']
    won   = b.get('won')
    score_str = (f"{info['score_h']}-{info['score_a']}"
                 if info.get('score_h') else b.get('score',''))
    ftr   = info['ftr'] or b.get('ftr','')

    # YES bet
    br_before_yes = kalshi_br
    raw_f     = kelly_raw(pf, ask)
    yes_stake = kelly_stake(pf, ask, kalshi_br)
    yes_pnl   = calc_pnl(yes_stake, ask, won)
    yes_stake = round(yes_stake, 2)
    kalshi_br = round(kalshi_br + yes_pnl, 2)

    b['kalshi_ask']   = ask
    b['kalshi_stake'] = yes_stake
    b['pin_fair']     = pf
    b['kalshi_pnl']   = yes_pnl
    b['kalshi_bankroll_after'] = kalshi_br
    if score_str:
        b['score'] = score_str
    new_bets.append(b)

    # NO bet on opponent if YES raw Kelly was < $1
    raw_dollars = br_before_yes * raw_f * 0.25 if raw_f > 0 else 0.0
    if raw_dollars < MIN_STAKE:
        opp_bid = info['opp_bid']
        opp_pf  = info['opp_pin_fair']
        if opp_bid > 0 and opp_pf > 0:
            no_ask   = round(1.0 - opp_bid, 4)
            p_no     = 1.0 - opp_pf
            no_raw_f = kelly_raw(p_no, no_ask)
            if no_raw_f > 0:
                no_stake = round(kelly_stake(p_no, no_ask, kalshi_br), 2)
                if side == 'away':
                    no_won   = (ftr != 'H') if ftr else None
                    no_label = 'Home NO'
                else:
                    no_won   = (ftr != 'A') if ftr else None
                    no_label = 'Away NO'
                no_pnl_val = calc_pnl(no_stake, no_ask, no_won)
                kalshi_br  = round(kalshi_br + no_pnl_val, 2)

                no_entry = {
                    'date': date, 'home': home, 'away': away,
                    'league': b.get('league',''), 'div': b.get('div',''),
                    'bet': no_label,
                    'fixture_id': b.get('fixture_id'),
                    'pin_fair': round(opp_pf, 6),
                    'kalshi_ask': no_ask,
                    'kalshi_stake': no_stake,
                    'kalshi_pnl': no_pnl_val,
                    'kalshi_bankroll_after': kalshi_br,
                    'won': no_won,
                    'score': score_str,
                    'ftr': ftr,
                    'resolved_at': b.get('resolved_at',''),
                    'is_no_bet': True,
                }
                new_bets.append(no_entry)
                no_bets_added += 1
                rs = 'W' if no_won else ('L' if no_won is False else '?')
                print(f"  NO {date} {home} vs {away} [{no_label}] ask={no_ask:.3f} "
                      f"stake=${no_stake} pnl=${no_pnl_val:+.2f} {rs} br=${kalshi_br}")

print(f"\nNO bets added: {no_bets_added}")
print(f"Final Kalshi bankroll: ${kalshi_br:.2f}")

BET_HISTORY.write_text(json.dumps(new_bets, indent=2))
json.dump({'bankroll': kalshi_br, 'updated': '2026-05-01'},
          open(KALSHI_BR, 'w'), indent=2)
print("Saved.")
