#!/usr/bin/env python3
"""Deep analysis of backtest trades — identifies failure patterns and root causes."""

from __future__ import annotations

import sys
from pathlib import Path
from datetime import datetime
from collections import Counter, defaultdict

import pandas as pd
import numpy as np

sys.path.insert(0, str(Path(__file__).parent.parent))


def analyze_trade_file(csv_path: str) -> dict:
    """Analyze a single trade CSV and return detailed metrics."""
    df = pd.read_csv(csv_path)
    if df.empty:
        return {}

    # Parse direction
    df["is_long"] = df["direction"].apply(
        lambda x: "BUY" in str(x) if pd.notna(x) else True
    )

    # Time-based analysis (compute BEFORE creating views)
    df["entry_dt"] = pd.to_datetime(df["entry_time"], unit="s")
    df["exit_dt"] = pd.to_datetime(df["exit_time"], unit="s")
    df["entry_hour"] = df["entry_dt"].dt.hour
    df["entry_dow"] = df["entry_dt"].dt.dayofweek  # 0=Mon
    df["hold_hours"] = ((df["exit_time"] - df["entry_time"]) / 3600).abs()
    df["trade_value"] = df["entry_price"] * df["quantity"]
    df["pnl_pct"] = np.where(df["trade_value"] > 0, df["pnl"] / df["trade_value"] * 100, 0)

    # Now create views
    long_trades = df[df["is_long"]]
    short_trades = df[~df["is_long"]]
    wins = df[df["pnl"] > 0]
    losses = df[df["pnl"] <= 0]

    # Compute effective RR per trade (abs(reward)/abs(risk))
    risk_dist = (df["entry_price"] - df["sl_price"]).abs()
    effective_rr = np.where(risk_dist > 0, (df["exit_price"] - df["entry_price"]).abs() / risk_dist, 0)
    # For SELL, reward is flipped
    short_mask = ~df["is_long"]
    effective_rr[short_mask] = np.where(
        risk_dist[short_mask] > 0,
        (df["entry_price"][short_mask] - df["exit_price"][short_mask]).abs() / risk_dist[short_mask],
        0,
    )

    # Win rate by hour
    wr_by_hour = {}
    for h in range(10, 19):
        subset = df[df["entry_hour"] == h]
        if len(subset) > 0:
            wr_by_hour[h] = (subset["pnl"] > 0).mean() * 100

    # Win rate by day of week
    wr_by_dow = {}
    for d in range(5):
        subset = df[df["entry_dow"] == d]
        if len(subset) > 0:
            wr_by_dow[d] = (subset["pnl"] > 0).mean() * 100

    # Holding time analysis
    avg_hold_win = wins["hold_hours"].mean() if len(wins) > 0 else 0
    avg_hold_loss = losses["hold_hours"].mean() if len(losses) > 0 else 0

    # PnL distribution (using trade value %)
    pnl_bins = {
        "large_loss_2pct": len(losses[losses["pnl_pct"] < -2.0]),
        "medium_loss_1_2pct": len(losses[(losses["pnl_pct"] >= -2.0) & (losses["pnl_pct"] < -1.0)]),
        "small_loss_0_1pct": len(losses[losses["pnl_pct"] >= -1.0]),
        "small_win_0_1pct": len(wins[(wins["pnl_pct"] > 0) & (wins["pnl_pct"] <= 1.0)]),
        "medium_win_1_2pct": len(wins[(wins["pnl_pct"] > 1.0) & (wins["pnl_pct"] <= 2.0)]),
        "large_win_2pct": len(wins[wins["pnl_pct"] > 2.0]),
    }

    # Commission impact
    total_commission = df["commission"].sum()
    total_slippage = df["slippage"].sum()
    total_costs = total_commission + total_slippage
    total_pnl = df["pnl"].sum()

    # Estimate SL-hit losses: exit_price within 0.3% of sl_price
    sl_tolerance = 0.003  # 0.3%
    sl_hit_mask = (losses["exit_price"] - losses["sl_price"]).abs() / losses["sl_price"].abs() < sl_tolerance
    sl_hit_losses = losses[sl_hit_mask]

    return {
        "total": len(df),
        "long": len(long_trades),
        "short": len(short_trades),
        "win_rate": (len(wins) / len(df) * 100) if len(df) > 0 else 0,
        "total_pnl": total_pnl,
        "total_costs": total_costs,
        "costs_pct_of_pnl": abs(total_costs / total_pnl * 100) if abs(total_pnl) > 1 else 0,
        "avg_effective_rr_win": effective_rr[df["pnl"] > 0].mean() if len(wins) > 0 else 0,
        "avg_effective_rr_loss": effective_rr[df["pnl"] <= 0].mean() if len(losses) > 0 else 0,
        "avg_hold_win_hours": avg_hold_win,
        "avg_hold_loss_hours": avg_hold_loss,
        "wr_by_hour": wr_by_hour,
        "wr_by_dow": wr_by_dow,
        "pnl_distribution": pnl_bins,
        "sl_hit_losses": len(sl_hit_losses),
        "sl_hit_pct": (len(sl_hit_losses) / len(losses) * 100) if len(losses) > 0 else 0,
        "avg_long_pnl": long_trades["pnl"].mean() if len(long_trades) > 0 else 0,
        "avg_short_pnl": short_trades["pnl"].mean() if len(short_trades) > 0 else 0,
    }


def main():
    logs_dir = Path("logs")
    tickers = ["ASTR", "GAZP", "LKOH", "MTSS", "NVTK", "PHOR", "PLZL", "ROSN", "SBER", "SNGSP", "VTBR"]

    print("=" * 120)
    print("DEEP TRADE ANALYSIS")
    print("=" * 120)

    all_results = {}

    for ticker in tickers:
        csv_path = logs_dir / f"trades_{ticker}_H1.csv"
        if not csv_path.exists():
            print(f"\n{ticker}: No trade file")
            continue

        result = analyze_trade_file(str(csv_path))
        all_results[ticker] = result

        print(f"\n{'─' * 80}")
        print(f"📊 {ticker} — {result['total']} trades ({result['long']} LONG, {result['short']} SHORT)")
        print(f"   Win Rate: {result['win_rate']:.1f}% | Total PnL: {result['total_pnl']:,.0f}")
        print(f"   Costs (comm+slip): {result['total_costs']:,.0f} ({result['costs_pct_of_pnl']:.1f}% of PnL)")
        print(f"   Avg Effective RR — Wins: {result['avg_effective_rr_win']:.2f} | Losses: {result['avg_effective_rr_loss']:.2f}")
        print(f"   Avg Hold Time — Wins: {result['avg_hold_win_hours']:.1f}h | Losses: {result['avg_hold_loss_hours']:.1f}h")

        # Win rate by hour
        print(f"   Win Rate by Hour:", end="")
        for h, wr in sorted(result["wr_by_hour"].items()):
            print(f" {h}h={wr:.0f}%", end="")
        print()

        # Win rate by day
        dow_names = ["Mon", "Tue", "Wed", "Thu", "Fri"]
        print(f"   Win Rate by Day:  ", end="")
        for d, wr in sorted(result["wr_by_dow"].items()):
            print(f" {dow_names[d]}={wr:.0f}%", end="")
        print()

        # PnL distribution
        pnl_dist = result["pnl_distribution"]
        print(f"   PnL Distribution:")
        for label, count in pnl_dist.items():
            pct = count / result["total"] * 100 if result["total"] > 0 else 0
            print(f"     {label}: {count} ({pct:.1f}%)")

        # SL hits
        loss_count = result['total'] - int(result['total'] * result['win_rate'] / 100)
        print(f"   SL-hit losses: {result['sl_hit_losses']}/{loss_count} "
              f"({result['sl_hit_pct']:.1f}% of losses)")

    # Cross-ticker summary
    print(f"\n{'=' * 120}")
    print("CROSS-TICKER SUMMARY")
    print(f"{'=' * 120}")

    # Find common failure patterns
    all_sl_hit_pct = np.mean([r["sl_hit_pct"] for r in all_results.values()])
    all_costs_impact = np.mean([r["costs_pct_of_pnl"] for r in all_results.values() if r["costs_pct_of_pnl"] != float("inf")])
    avg_wr = np.mean([r["win_rate"] for r in all_results.values()])
    avg_eff_rr_win = np.mean([r["avg_effective_rr_win"] for r in all_results.values()])
    avg_eff_rr_loss = np.mean([r["avg_effective_rr_loss"] for r in all_results.values()])

    print(f"\n📈 Aggregate Statistics:")
    print(f"   Average Win Rate: {avg_wr:.1f}%")
    print(f"   Average Effective RR (wins): {avg_eff_rr_win:.2f}")
    print(f"   Average Effective RR (losses): {avg_eff_rr_loss:.2f}")
    print(f"   Average SL-hit % of losses: {all_sl_hit_pct:.1f}%")
    print(f"   Average Cost Impact: {all_costs_impact:.1f}% of total PnL")

    # Worst hours overall
    hour_wr = defaultdict(list)
    for t, r in all_results.items():
        for h, wr in r.get("wr_by_hour", {}).items():
            hour_wr[h].append(wr)
    print(f"\n⏰ Best/Worst Entry Hours (avg WR):")
    for h in sorted(hour_wr.keys()):
        avg = np.mean(hour_wr[h])
        print(f"   {h}:00 MSK — {avg:.1f}% WR ({len(hour_wr[h])} tickers)")

    # Correlation: more signals = worse PnL?
    print(f"\n🔗 Signal Count vs PnL Correlation:")
    ticker_signals = []
    ticker_pnls = []
    for t, r in all_results.items():
        ticker_signals.append(r["total"])
        ticker_pnls.append(r["total_pnl"])
    if len(ticker_signals) > 1:
        corr = np.corrcoef(ticker_signals, ticker_pnls)[0, 1]
        print(f"   Correlation: {corr:.3f} {'(more trades → worse PnL)' if corr < -0.3 else ''}")


if __name__ == "__main__":
    main()
