"""Weekly performance report from journal entries."""
from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime

from .journal import TradeEntry


@dataclass
class WeeklyReport:
    week: str               # "YYYY-WW"
    n_trades: int
    n_wins: int
    n_losses: int
    win_rate: float
    pnl_r: float            # sum in R multiples
    avg_slippage: float | None  # seconds from signal detection to entry; None if data missing


def iso_week(ts_iso: str) -> str:
    """Return 'YYYY-WW' (ISO calendar week) for the given ISO timestamp."""
    dt = datetime.fromisoformat(ts_iso)
    cal = dt.isocalendar()
    return f"{cal.year}-{cal.week:02d}"


def _pnl_r(entry: TradeEntry) -> float | None:
    """R-multiple PnL for a closed trade. None if exit is missing or risk is zero."""
    if entry.exit is None:
        return None
    risk = entry.entry - entry.sl  # positive for BUY (entry > sl), negative for SELL
    if risk == 0:
        return None
    return (entry.exit - entry.entry) / risk


def weekly_report(entries: list[TradeEntry], week: str) -> WeeklyReport:
    """Compute a WeeklyReport for entries belonging to *week* ('YYYY-WW')."""
    week_entries = [e for e in entries if iso_week(e.ts) == week]
    closed = [e for e in week_entries if e.outcome != "open"]

    n_trades = len(closed)
    n_wins = sum(1 for e in closed if e.outcome in {"tp1", "tp2"})
    n_losses = sum(1 for e in closed if e.outcome in {"sl", "manual"})
    win_rate = n_wins / n_trades if n_trades > 0 else 0.0

    pnl_values = [r for e in closed if (r := _pnl_r(e)) is not None]
    pnl_r = sum(pnl_values)

    slippages: list[float] = []
    for e in closed:
        if e.detected_ts and e.ts:
            try:
                dt_entry = datetime.fromisoformat(e.ts)
                dt_detect = datetime.fromisoformat(e.detected_ts)
                slippages.append((dt_entry - dt_detect).total_seconds())
            except ValueError:
                pass
    avg_slippage = sum(slippages) / len(slippages) if slippages else None

    return WeeklyReport(
        week=week,
        n_trades=n_trades,
        n_wins=n_wins,
        n_losses=n_losses,
        win_rate=win_rate,
        pnl_r=pnl_r,
        avg_slippage=avg_slippage,
    )
