#!/usr/bin/env python3
"""
PolyEdge — Backtest Runner

Usage:
  python3 run_backtest.py                    # Default: Jan 2026, $1000
  python3 run_backtest.py --month 202512     # Specific month
  python3 run_backtest.py --bankroll 500     # Custom bankroll
  python3 run_backtest.py --sweep            # Parameter sweep
"""

import sys
import os
import argparse
import json
from datetime import datetime

# Add parent dir to path
sys.path.insert(0, os.path.dirname(__file__))

from backtest import BacktestEngine
from config import INITIAL_BANKROLL


DATA_DIR = "/var/www/html/crpytotradingbot/data/monthly"
RESULTS_DIR = "/var/www/html/crpytotradingbot/results"


def get_monthly_file(month: str) -> str:
    """Get path to monthly data file."""
    return os.path.join(DATA_DIR, f"BTCUSD_{month}.csv")


def run_single(month: str, bankroll: float, noise: float = 0.03, 
               max_rows: int = 2000000, save: bool = True) -> dict:
    """Run a single backtest."""
    filepath = get_monthly_file(month)
    if not os.path.exists(filepath):
        print(f"ERROR: Data file not found: {filepath}")
        return {}
    
    print(f"\n{'='*60}")
    print(f"PolyEdge Backtest: {month}")
    print(f"Bankroll: ${bankroll:,.2f} | Noise: {noise} | Max rows: {max_rows:,}")
    print(f"{'='*60}")
    
    engine = BacktestEngine(bankroll)
    engine.load_data(filepath, max_rows)
    
    stats = engine.run(market_noise=noise)
    
    # Print results
    print(f"\n{'='*60}")
    print(f"RESULTS")
    print(f"{'='*60}")
    print(f"  Bankroll: ${bankroll:,.2f} → ${stats['bankroll']:,.2f}")
    print(f"  Net P&L:  ${stats['total_pnl']:+,.2f} ({stats['return_pct']:+.2f}%)")
    print(f"  Trades:   {stats['total_trades']}")
    print(f"  Win Rate: {stats['win_rate']:.1f}%")
    print(f"  Avg Win:  ${stats['avg_win']:.2f}")
    print(f"  Avg Loss: ${stats['avg_loss']:.2f}")
    print(f"  PF:       {stats['profit_factor']:.2f}")
    print(f"  Max DD:   {stats['max_drawdown_pct']:.1f}%")
    print(f"  Fees:     ${stats['total_fees']:.2f}")
    print(f"  Period:   {stats.get('start_date', '?')} to {stats.get('end_date', '?')}")
    
    if save:
        engine.save_results(RESULTS_DIR)
    
    return stats


def run_sweep():
    """Run parameter sweep across noise levels and months."""
    months = ["202508", "202509", "202510", "202511", "202512", "202601"]
    noise_levels = [0.02, 0.03, 0.05, 0.08, 0.10]
    bankroll = 1000
    
    print(f"\n{'='*70}")
    print(f"PolyEdge PARAMETER SWEEP")
    print(f"{'='*70}")
    print(f"Months: {', '.join(months)}")
    print(f"Noise levels: {noise_levels}")
    print(f"Bankroll: ${bankroll:,.2f}")
    
    results = []
    
    for noise in noise_levels:
        for month in months:
            filepath = get_monthly_file(month)
            if not os.path.exists(filepath):
                continue
            
            engine = BacktestEngine(bankroll)
            engine.load_data(filepath, max_rows=2000000)
            stats = engine.run(market_noise=noise)
            stats['month'] = month
            stats['noise'] = noise
            results.append(stats)
            
            wr = stats['win_rate']
            pnl = stats['total_pnl']
            dd = stats['max_drawdown_pct']
            trades = stats['total_trades']
            print(f"  Noise={noise:.2f} Month={month}: {trades} trades, WR={wr:.1f}%, P&L=${pnl:+,.2f}, DD={dd:.1f}%")
    
    # Summary table
    print(f"\n{'='*70}")
    print(f"SWEEP SUMMARY")
    print(f"{'='*70}")
    print(f"{'Noise':>6} {'Month':>7} {'Trades':>7} {'WR%':>6} {'Net P&L':>10} {'DD%':>7} {'PF':>6}")
    print("-" * 55)
    for r in results:
        print(f"{r['noise']:>6.2f} {r['month']:>7} {r['total_trades']:>7} {r['win_rate']:>5.1f}% ${r['total_pnl']:>+9,.2f} {r['max_drawdown_pct']:>6.1f}% {r['profit_factor']:>5.2f}")
    
    # Save sweep results
    with open(os.path.join(RESULTS_DIR, "polyedge_sweep.json"), 'w') as f:
        json.dump(results, f, indent=2, default=str)
    
    print(f"\nSweep saved to {RESULTS_DIR}/polyedge_sweep.json")


def run_multimonth(months: list, bankroll: float, noise: float = 0.03):
    """Run backtest across multiple months with equity carry-forward."""
    print(f"\n{'='*60}")
    print(f"PolyEdge Multi-Month: {' → '.join(months)}")
    print(f"Start: ${bankroll:,.2f} | Noise: {noise}")
    print(f"{'='*60}")
    
    current_bankroll = bankroll
    all_stats = []
    
    for month in months:
        filepath = get_monthly_file(month)
        if not os.path.exists(filepath):
            print(f"  Skipping {month} (no data)")
            continue
        
        engine = BacktestEngine(current_bankroll)
        engine.load_data(filepath, max_rows=2000000)
        stats = engine.run(market_noise=noise)
        stats['month'] = month
        stats['start_bankroll'] = current_bankroll
        
        print(f"  {month}: ${current_bankroll:,.2f} → ${stats['bankroll']:,.2f} ({stats['return_pct']:+.1f}%) | {stats['total_trades']} trades, WR {stats['win_rate']:.1f}%, DD {stats['max_drawdown_pct']:.1f}%")
        
        current_bankroll = stats['bankroll']
        all_stats.append(stats)
        
        if current_bankroll <= 0:
            print("  ⚠️ BUSTED — stopping")
            break
    
    # Total summary
    total_return = (current_bankroll / bankroll - 1) * 100
    total_trades = sum(s['total_trades'] for s in all_stats)
    max_dd = max(s['max_drawdown_pct'] for s in all_stats) if all_stats else 0
    
    print(f"\n{'='*60}")
    print(f"MULTI-MONTH TOTAL")
    print(f"{'='*60}")
    print(f"  ${bankroll:,.2f} → ${current_bankroll:,.2f} ({total_return:+.2f}%)")
    print(f"  Total trades: {total_trades}")
    print(f"  Max DD: {max_dd:.1f}%")
    
    return all_stats


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="PolyEdge Backtest")
    parser.add_argument("--month", default="202601", help="Month to test (YYYYMM)")
    parser.add_argument("--bankroll", type=float, default=INITIAL_BANKROLL)
    parser.add_argument("--noise", type=float, default=0.03, help="Market noise level")
    parser.add_argument("--rows", type=int, default=2000000, help="Max tick rows to load")
    parser.add_argument("--sweep", action="store_true", help="Run parameter sweep")
    parser.add_argument("--multi", nargs="+", help="Multi-month run (e.g. --multi 202508 202509)")
    parser.add_argument("--no-save", action="store_true")
    
    args = parser.parse_args()
    
    if args.sweep:
        run_sweep()
    elif args.multi:
        run_multimonth(args.multi, args.bankroll, args.noise)
    else:
        run_single(args.month, args.bankroll, args.noise, args.rows, not args.no_save)
