"""Equity page — cumulative PnL, drawdown, distributions."""

from __future__ import annotations

import os
from collections import Counter
from datetime import UTC, datetime, timedelta
from pathlib import Path

import pandas as pd
import plotly.graph_objects as go
import streamlit as st

from cerbero_bite.gui.data_layer import (
    DEFAULT_DB_PATH,
    compute_equity_curve,
    compute_kpis,
    compute_monthly_stats,
    load_closed_positions,
)


def _resolve_db() -> Path:
    return Path(os.environ.get("CERBERO_BITE_GUI_DB", DEFAULT_DB_PATH))


def _date_window(label: str) -> tuple[datetime | None, datetime | None]:
    """Selettore della finestra temporale per l'analitica."""
    options = {
        "Tutto lo storico": (None, None),
        "Ultimi 30 giorni": (datetime.now(UTC) - timedelta(days=30), None),
        "Ultimi 90 giorni": (datetime.now(UTC) - timedelta(days=90), None),
        "Da inizio anno": (
            datetime(datetime.now(UTC).year, 1, 1, tzinfo=UTC),
            None,
        ),
    }
    pick = st.selectbox(label, list(options.keys()), index=0)
    return options[pick]


def render() -> None:
    st.title("📈 Equity")
    st.caption(
        "P&L realizzato cumulato, drawdown e distribuzione per trade. "
        "Calcolato dalle posizioni chiuse in `data/state.sqlite`."
    )

    start, end = _date_window("Finestra")

    db_path = _resolve_db()
    positions = load_closed_positions(db_path=db_path, start=start, end=end)

    if not positions:
        st.info(
            "Nessuna posizione chiusa nella finestra selezionata. "
            "La curva equity si popolerà non appena il motore chiuderà "
            "il primo trade."
        )
        return

    # Striscia KPI
    kpis = compute_kpis(positions)
    cols = st.columns(5)
    cols[0].metric("Trade chiusi", kpis.n_trades)
    cols[1].metric("Win rate", f"{kpis.win_rate:.0%}")
    cols[2].metric("P&L totale", f"${float(kpis.total_pnl_usd):+.2f}")
    cols[3].metric("Edge / trade", f"${float(kpis.edge_per_trade_usd):+.2f}")
    cols[4].metric(
        "Max drawdown",
        f"${float(kpis.max_drawdown_usd):.2f}",
        delta=f"{kpis.max_drawdown_pct:.1%}",
        delta_color="inverse",
    )

    st.divider()

    # Equity curve + drawdown
    curve = compute_equity_curve(positions)
    df = pd.DataFrame(
        {
            "timestamp": [p.timestamp for p in curve],
            "cumulative_pnl_usd": [float(p.cumulative_pnl_usd) for p in curve],
            "drawdown_usd": [float(p.drawdown_usd) for p in curve],
            "realized_pnl_usd": [float(p.realized_pnl_usd) for p in curve],
        }
    )

    st.subheader("P&L cumulato (USD)")
    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            x=df["timestamp"],
            y=df["cumulative_pnl_usd"],
            mode="lines+markers",
            name="P&L cumulato",
            line={"color": "#2ecc71", "width": 2},
        )
    )
    fig.add_hline(y=0, line_dash="dot", line_color="grey", opacity=0.5)
    fig.update_layout(
        height=320,
        margin={"l": 10, "r": 10, "t": 30, "b": 10},
        xaxis_title=None,
        yaxis_title="USD",
    )
    st.plotly_chart(fig, use_container_width=True)

    st.subheader("Drawdown (USD)")
    dd_fig = go.Figure()
    dd_fig.add_trace(
        go.Scatter(
            x=df["timestamp"],
            y=-df["drawdown_usd"],
            mode="lines",
            fill="tozeroy",
            name="drawdown",
            line={"color": "#e74c3c", "width": 1.5},
        )
    )
    dd_fig.update_layout(
        height=220,
        margin={"l": 10, "r": 10, "t": 30, "b": 10},
        xaxis_title=None,
        yaxis_title="USD",
    )
    st.plotly_chart(dd_fig, use_container_width=True)

    # Distribuzione P&L
    st.subheader("Distribuzione P&L per motivo di chiusura")
    by_reason: dict[str, list[float]] = {}
    for pos in positions:
        if pos.pnl_usd is None:
            continue
        by_reason.setdefault(pos.close_reason or "(sconosciuto)", []).append(
            float(pos.pnl_usd)
        )

    counts = Counter(
        (pos.close_reason or "(sconosciuto)") for pos in positions
    )
    cols = st.columns(min(len(counts), 6) or 1)
    for col, (reason, count) in zip(cols, counts.most_common(6), strict=False):
        col.metric(reason, count)

    hist_fig = go.Figure()
    for reason, pnls in by_reason.items():
        hist_fig.add_trace(
            go.Histogram(x=pnls, name=reason, opacity=0.6, nbinsx=30)
        )
    hist_fig.update_layout(
        barmode="overlay",
        height=320,
        margin={"l": 10, "r": 10, "t": 30, "b": 10},
        xaxis_title="P&L (USD)",
        yaxis_title="numero trade",
        legend={"orientation": "h", "y": 1.1},
    )
    st.plotly_chart(hist_fig, use_container_width=True)

    # Tabella mensile
    st.subheader("Statistiche mensili")
    months = compute_monthly_stats(positions)
    rows = [
        {
            "mese": m.year_month,
            "trade": m.n_trades,
            "vittorie": m.n_wins,
            "win rate": f"{m.win_rate:.0%}",
            "P&L (USD)": f"{float(m.pnl_usd):+.2f}",
            "media / trade": f"{float(m.avg_pnl_usd):+.2f}",
        }
        for m in months
    ]
    st.dataframe(rows, use_container_width=True, hide_index=True)


render()
