"""
Weekly bet summary — emails previous week's (Mon–Sun) bets.
Scheduled Monday nights via Task Scheduler.

Usage: python weekly_bet_summary.py
"""
import json, sys, smtplib, io
from datetime import date, timedelta
from pathlib import Path
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

sys.path.insert(0, r'E:\soccer')
from forward_test_drift_momentum import (
    build_signals, _kelly, COMBOS, BANK0, MIN_STAKE, FLAT_DOLLAR, FREEZE_DATE,
    log_forward_snapshot)

sys.stdout.reconfigure(encoding='utf-8', errors='replace')

BET_HISTORY = Path(r'E:\soccer\data\bet_history.json')

def _load_env(path):
    env = {}
    try:
        for line in open(path):
            line = line.strip()
            if line and not line.startswith('#') and '=' in line:
                k, v = line.split('=', 1)
                env[k.strip()] = v.strip()
    except Exception:
        pass
    return env

_env               = _load_env(r'E:\soccer\.env')
EMAIL_ADDRESS      = _env.get('EMAIL_SENDER', '')
EMAIL_RECIPIENT    = _env.get('EMAIL_RECIPIENT', '')
EMAIL_APP_PASSWORD = _env.get('EMAIL_APP_PASSWORD', '')

def send_email(subject, html_body, inline_images=None):
    """inline_images: list of (cid, png_bytes) tuples to embed via cid: references."""
    msg = MIMEMultipart('related')
    msg['Subject'] = subject
    msg['From']    = EMAIL_ADDRESS
    msg['To']      = EMAIL_RECIPIENT
    alt = MIMEMultipart('alternative')
    msg.attach(alt)
    alt.attach(MIMEText(html_body, 'html'))
    for cid, png_bytes in (inline_images or []):
        img = MIMEImage(png_bytes, _subtype='png')
        img.add_header('Content-ID', f'<{cid}>')
        img.add_header('Content-Disposition', 'inline', filename=f'{cid}.png')
        msg.attach(img)
    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as srv:
        srv.login(EMAIL_ADDRESS, EMAIL_APP_PASSWORD)
        srv.sendmail(EMAIL_ADDRESS, EMAIL_RECIPIENT, msg.as_string())

def build_equity_chart(start=BANK0):
    """Return PNG bytes of the four backtest/forward strategy equity paths
    (baseline/momentum x flat/kelly) over the full live_data signal history.
    Blue = baseline, red = momentum; dashed = flat $10, solid = kelly.
    A vertical line marks FREEZE_DATE (left = in-sample, right = forward/OOS)."""
    from datetime import datetime as _dt

    def _d(gd):
        try: return _dt.strptime(gd, '%Y-%m-%d')
        except Exception: return None

    sigs = build_signals()
    if not sigs:
        return None

    styles = {'bf': '#1f77b4', 'bk': '#1f77b4', 'mf': '#d62728', 'mk': '#d62728',
              'ef': '#2ca02c'}
    dashes = {'flat': (4, 3), 'kelly': None}

    fig, ax = plt.subplots(figsize=(11, 5.5))
    plotted = False
    for tag, sig, stk, label in COMBOS:
        late = sig in ('momentum', 'edge')
        bank = start; xs = []; ys = []
        for b in sorted(sigs, key=lambda s: s['gd']):
            if sig == 'momentum' and b['drift'] < 0:
                continue
            a = b['aL'] if late else b['a0']
            p = b['pL'] if late else b['p0']
            if not (0 < a < 1):
                continue
            if sig == 'edge' and not (p > a):
                continue
            d = _d(b['gd'])
            if d is None:
                continue
            unitnet = (1 - a) / a if b['won'] else -1.0
            if stk == 'kelly':
                frac = _kelly(p, a)
                if frac <= 0:
                    continue
                stake = min(max(frac * bank, MIN_STAKE), bank)
            else:
                stake = FLAT_DOLLAR
            bank += stake * unitnet
            xs.append(d); ys.append(bank)
        if not xs:
            continue
        roi = (bank / start - 1) * 100
        ls = '--' if stk == 'flat' else '-'
        ax.plot(xs, ys, color=styles[tag], linestyle=ls, linewidth=1.8,
                label=f'{label} (${bank:,.0f}, {roi:+.1f}%, n={len(xs)})')
        plotted = True

    if not plotted:
        plt.close(fig)
        return None

    ax.axhline(start, color='gray', linestyle=':', linewidth=1, alpha=0.6)
    fz = _d(FREEZE_DATE)
    if fz is not None:
        ax.axvline(fz, color='black', linestyle='--', linewidth=1, alpha=0.4)
        ax.text(fz, ax.get_ylim()[1], ' forward →', va='top', ha='left',
                fontsize=8, color='#555')
    ax.set_xlabel('Game date')
    ax.set_ylabel('Bankroll ($)')
    ax.set_title('Strategy equity paths — baseline vs momentum × flat vs kelly')
    ax.legend(loc='best', frameon=True, fontsize=9)
    ax.grid(True, alpha=0.3)
    fig.autofmt_xdate()
    fig.tight_layout()

    buf = io.BytesIO()
    fig.savefig(buf, format='png', dpi=120)
    plt.close(fig)
    return buf.getvalue()

def main():
    today = date.today()
    # Previous week: Mon–Sun ending yesterday (Sunday)
    # On Monday, "last Sunday" = today - 1, "last Monday" = today - 7
    last_sunday = today - timedelta(days=1)
    last_monday = last_sunday - timedelta(days=6)
    week_label  = f"{last_monday.strftime('%b %d')} – {last_sunday.strftime('%b %d, %Y')}"

    bets = json.loads(BET_HISTORY.read_text()) if BET_HISTORY.exists() else []
    week_bets = [
        b for b in bets
        if last_monday.isoformat() <= b.get('date', '') <= last_sunday.isoformat()
    ]

    def _stake(b):  return b.get('stake') or b.get('kalshi_stake') or 0
    def _pnl(b):    return b.get('pnl') or b.get('kalshi_pnl') or 0
    def _odds(b):   return b.get('b365') or b.get('kalshi_ask') or '—'
    def _platform(b): return 'Kalshi' if not b.get('stake') and b.get('kalshi_stake') else 'B365'

    wins   = sum(1 for b in week_bets if b.get('won'))
    losses = sum(1 for b in week_bets if b.get('won') is False and not b.get('void'))
    net    = sum(_pnl(b) for b in week_bets)
    staked = sum(_stake(b) for b in week_bets)
    roi    = (net / staked * 100) if staked else 0

    color = '#27ae60' if net >= 0 else '#e74c3c'

    rows_html = ''
    for b in week_bets:
        won = b.get('won')
        result_color = '#27ae60' if won else ('#e74c3c' if won is False else '#888')
        pnl = _pnl(b)
        score = b.get('score', '?')
        clv = b.get('clv_b365') or b.get('clv_kalshi') or ''
        clv_str = f"{clv:+.1f}%" if isinstance(clv, (int, float)) else ''
        platform = _platform(b)
        rows_html += f"""
        <tr>
          <td>{b['date']}</td>
          <td>{b['home']} vs {b['away']}</td>
          <td>{b.get('league','')}</td>
          <td>{b.get('bet','')}</td>
          <td>{platform}</td>
          <td>{_odds(b)}</td>
          <td>{clv_str}</td>
          <td>${_stake(b):.2f}</td>
          <td>{score}</td>
          <td style="color:{result_color};font-weight:bold">${pnl:+.2f}</td>
        </tr>"""

    if not week_bets:
        rows_html = '<tr><td colspan="10" style="text-align:center">No bets this week</td></tr>'

    try:
        kalshi_br = json.loads(Path(r'E:\soccer\data\kalshi_bankroll.json').read_text())['bankroll']
        kalshi_br_str = f'${kalshi_br:,.2f}'
    except Exception:
        kalshi_br_str = 'N/A'

    chart_png = build_equity_chart()
    chart_html = ('<img src="cid:equitychart" alt="strategy equity paths" '
                  'style="max-width:100%;border:1px solid #ddd"><br><br>'
                  if chart_png else '<p><i>(no signal history available)</i></p>')

    html = f"""<html><body style="font-family:sans-serif;max-width:960px">
    <h2>Weekly Bet Summary — {week_label}</h2>
    <h3 style="margin-top:24px;margin-bottom:6px">Strategy equity paths (baseline vs momentum × flat vs kelly)</h3>
    {chart_html}
    <table style="border-collapse:collapse;margin-bottom:16px">
      <tr>
        <td style="padding:8px 20px;background:#f5f5f5;border-radius:4px">
          <b>Record</b><br>{wins}W / {losses}L
        </td>
        <td style="padding:8px 20px;background:#f5f5f5;border-radius:4px">
          <b>Net P&L</b><br><span style="color:{color};font-weight:bold">${net:+.2f}</span>
        </td>
        <td style="padding:8px 20px;background:#f5f5f5;border-radius:4px">
          <b>ROI</b><br><span style="color:{color}">{roi:+.1f}%</span>
        </td>
        <td style="padding:8px 20px;background:#f5f5f5;border-radius:4px">
          <b>Staked</b><br>${staked:.2f}
        </td>
        <td style="padding:8px 20px;background:#f5f5f5;border-radius:4px">
          <b>Kalshi Bankroll</b><br>{kalshi_br_str}
        </td>
      </tr>
    </table>
    <table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
      <tr style="background:#eee">
        <th>Date</th><th>Match</th><th>League</th><th>Bet</th>
        <th>Platform</th><th>Odds/Mid</th><th>CLV</th><th>Stake</th><th>Score</th><th>P&L</th>
      </tr>
      {rows_html}
    </table>
    </body></html>"""

    subject = f"Weekly Bets {week_label} — {wins}W/{losses}L  ${net:+.2f}"
    images = [('equitychart', chart_png)] if chart_png else []
    send_email(subject, html, inline_images=images)
    print(f"Sent: {subject}")

    # grow the forward-test log on the weekly schedule (one dated snapshot/run)
    try:
        snap = log_forward_snapshot()
        print(f"Appended forward-test snapshot (momentum-flat fwd n={snap['mf_n']})")
    except Exception as e:
        print(f"WARN: forward-test snapshot logging failed: {e}")

    # parallel forward-tracker: honest power-de-vig band [0.07,0.20) vs live band
    # [0.05,0.12). OOS evidence before any live de-vig/band change. NOTHING traded.
    try:
        from research.forward_test_devig_band import log_snapshot as _devig_log
        d = _devig_log()
        print(f"Appended de-vig band snapshot (honest fwd n={d['honest_n']}, live fwd n={d['live_n']})")
    except Exception as e:
        print(f"WARN: de-vig band snapshot logging failed: {e}")

    # parallel forward-tracker: cross-book UNIQUE (one book fires) vs OVERLAP (both
    # fire) [0.05,0.12) bets. Unique backtested +62% z+3.52 (held OOS); confirms the
    # 2nd book validates Pinnacle's fair. Inert until live Poly feed is back in season.
    try:
        from research.forward_test_unique_book import log_snapshot as _unique_log
        u = _unique_log()
        print(f"Appended cross-book snapshot (xlow PRIMARY fwd n={u['xlow_n']}, "
              f"unique n={u['unique_n']}, overlap n={u['overlap_n']})")
    except Exception as e:
        print(f"WARN: cross-book snapshot logging failed: {e}")

if __name__ == '__main__':
    main()
