"""Bar chart builders for HTML reports."""

from __future__ import annotations

from typing import TYPE_CHECKING

import plotly.graph_objects as go
from plotly.subplots import make_subplots

from .theme import DARK_THEME, FACTION_COLORS, to_html

if TYPE_CHECKING:
    from ..loaders.elo import EloData
    from ..loaders.tuning import TuningData
    from ..loaders.validation import DeckStats, ValidationData


def create_deck_winrate_bar(deck_stats: list[DeckStats]) -> str:
    """Create a horizontal bar chart of deck win rates.

    Args:
        deck_stats: List of DeckStats objects

    Returns:
        HTML string with embedded Plotly chart
    """
    # Sort by win rate descending
    sorted_stats = sorted(deck_stats, key=lambda d: d.win_rate, reverse=True)

    names = [f"{d.commander_name}" for d in sorted_stats]
    win_rates = [d.win_rate * 100 for d in sorted_stats]
    ci_lower = [(d.win_rate - d.win_rate_ci_lower) * 100 for d in sorted_stats]
    ci_upper = [(d.win_rate_ci_upper - d.win_rate) * 100 for d in sorted_stats]
    colors = [FACTION_COLORS.get(d.faction, DARK_THEME["text_secondary"]) for d in sorted_stats]

    fig = go.Figure()

    fig.add_trace(
        go.Bar(
            y=names,
            x=win_rates,
            orientation="h",
            marker_color=colors,
            error_x={"type": "data", "symmetric": False, "array": ci_upper, "arrayminus": ci_lower},
            hovertemplate="<b>%{y}</b><br>Win Rate: %{x:.1f}%<extra></extra>",
        )
    )

    # Add balanced zone (40-60%)
    fig.add_vrect(
        x0=40,
        x1=60,
        fillcolor="rgba(0, 210, 106, 0.1)",
        line_width=0,
        annotation_text="Balanced",
        annotation_position="top left",
        annotation_font_color=DARK_THEME["success"],
    )

    # Add 50% reference line
    fig.add_vline(x=50, line_dash="dash", line_color=DARK_THEME["text_secondary"], line_width=1)

    fig.update_layout(
        title={"text": "Deck Win Rates", "font": {"color": DARK_THEME["text_primary"]}},
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        xaxis={
            "title": "Win Rate (%)",
            "range": [0, 100],
            "gridcolor": DARK_THEME["grid"],
            "zeroline": False,
        },
        yaxis={"title": None, "gridcolor": DARK_THEME["grid"], "autorange": "reversed"},
        height=max(300, len(deck_stats) * 40),
        margin={"t": 50, "b": 50, "l": 150, "r": 30},
        showlegend=False,
    )

    return to_html(fig)


def create_p1_p2_chart(data: ValidationData) -> str:
    """Create a P1/P2 win rate visualization.

    Args:
        data: ValidationData with P1/P2 diagnostics

    Returns:
        HTML string with embedded Plotly chart
    """
    p1_diag = data.summary.get("p1_p2_diagnostics", {})
    p1_rate = p1_diag.get("overall_p1_win_rate", 0.5) * 100
    p1_ci_lower = p1_diag.get("overall_p1_ci_lower", 0.45) * 100
    p1_ci_upper = p1_diag.get("overall_p1_ci_upper", 0.55) * 100

    fig = go.Figure()

    # P1 bar with error bars
    fig.add_trace(
        go.Bar(
            x=["Player 1 Win Rate"],
            y=[p1_rate],
            marker_color=FACTION_COLORS["argentum"],
            error_y={
                "type": "data",
                "symmetric": False,
                "array": [p1_ci_upper - p1_rate],
                "arrayminus": [p1_rate - p1_ci_lower],
                "color": DARK_THEME["text_primary"],
            },
            hovertemplate=f"P1 Win Rate: {p1_rate:.1f}%<br>95% CI: [{p1_ci_lower:.1f}%, {p1_ci_upper:.1f}%]<extra></extra>",
        )
    )

    # Add 50% reference line
    fig.add_hline(y=50, line_dash="dash", line_color=DARK_THEME["text_secondary"], line_width=2)

    # Add balanced zone
    fig.add_hrect(
        y0=45,
        y1=55,
        fillcolor="rgba(0, 210, 106, 0.1)",
        line_width=0,
    )

    fig.update_layout(
        title={"text": "P1/P2 Balance", "font": {"color": DARK_THEME["text_primary"]}},
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        yaxis={
            "title": "Win Rate (%)",
            "range": [30, 70],
            "gridcolor": DARK_THEME["grid"],
        },
        xaxis={"title": None},
        height=250,
        margin={"t": 50, "b": 30, "l": 60, "r": 30},
        showlegend=False,
    )

    return to_html(fig)


def create_convergence_status(tuning_experiments: list[TuningData]) -> str:
    """Create a status summary chart for experiment convergence.

    Args:
        tuning_experiments: List of TuningData objects

    Returns:
        HTML string with embedded Plotly chart
    """
    names = []
    fitness_values = []
    colors = []

    for data in tuning_experiments:
        names.append(data.tag[:20])
        fitness_values.append(data.final_fitness)
        conv_info = data.get_convergence_info()
        if conv_info["converged"]:
            colors.append(DARK_THEME["success"])
        else:
            colors.append(DARK_THEME["warning"])

    fig = go.Figure(
        data=[
            go.Bar(
                x=names,
                y=fitness_values,
                marker_color=colors,
                hovertemplate="<b>%{x}</b><br>Fitness: %{y:.1f}<extra></extra>",
            )
        ]
    )

    fig.update_layout(
        title={
            "text": "Final Fitness by Experiment",
            "font": {"color": DARK_THEME["text_primary"]},
        },
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        xaxis={
            "title": None,
            "tickangle": 45,
        },
        yaxis={
            "title": "Fitness",
            "gridcolor": DARK_THEME["grid"],
        },
        height=300,
        margin={"t": 50, "b": 100, "l": 60, "r": 30},
        showlegend=False,
    )

    return to_html(fig)


def create_elo_rankings_bar(elo_data: EloData) -> str:
    """Create a horizontal bar chart of ELO ratings.

    Args:
        elo_data: EloData object with ratings

    Returns:
        HTML string with embedded Plotly chart
    """
    ranked_decks = elo_data.get_ranked_decks()

    names = [d.commander_name or d.deck_id for d in ranked_decks]
    ratings = [d.rating for d in ranked_decks]
    colors = [FACTION_COLORS.get(d.faction or "", DARK_THEME["text_secondary"]) for d in ranked_decks]
    win_rates = [d.win_rate * 100 for d in ranked_decks]

    fig = go.Figure()

    fig.add_trace(
        go.Bar(
            y=names,
            x=ratings,
            orientation="h",
            marker_color=colors,
            customdata=win_rates,
            hovertemplate="<b>%{y}</b><br>ELO: %{x:.0f}<br>Win Rate: %{customdata:.1f}%<extra></extra>",
        )
    )

    # Add 1500 baseline reference
    fig.add_vline(x=1500, line_dash="dash", line_color=DARK_THEME["text_secondary"], line_width=1)

    fig.update_layout(
        title={"text": "ELO Ratings", "font": {"color": DARK_THEME["text_primary"]}},
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        xaxis={
            "title": "ELO Rating",
            "gridcolor": DARK_THEME["grid"],
            "zeroline": False,
        },
        yaxis={"title": None, "gridcolor": DARK_THEME["grid"], "autorange": "reversed"},
        height=max(300, len(ranked_decks) * 35),
        margin={"t": 50, "b": 50, "l": 150, "r": 30},
        showlegend=False,
    )

    return to_html(fig)


def create_faction_winrate_bar(faction_win_rates: dict[str, float]) -> str:
    """Create a bar chart of overall faction win rates.

    Args:
        faction_win_rates: Dict of faction -> win_rate (0-1)

    Returns:
        HTML string with embedded Plotly chart
    """
    factions = list(faction_win_rates.keys())
    win_rates = [faction_win_rates[f] * 100 for f in factions]
    colors = [FACTION_COLORS.get(f, DARK_THEME["text_secondary"]) for f in factions]

    fig = go.Figure()

    fig.add_trace(
        go.Bar(
            x=[f.title() for f in factions],
            y=win_rates,
            marker_color=colors,
            text=[f"{wr:.1f}%" for wr in win_rates],
            textposition="outside",
            hovertemplate="<b>%{x}</b><br>Win Rate: %{y:.1f}%<extra></extra>",
        )
    )

    # Add 50% reference line
    fig.add_hline(
        y=50, line_dash="dash", line_color=DARK_THEME["warning"], line_width=2
    )

    # Add balanced zone (45-55%)
    fig.add_hrect(
        y0=45,
        y1=55,
        fillcolor="rgba(0, 210, 106, 0.1)",
        line_width=0,
    )

    fig.update_layout(
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        yaxis={
            "title": "Win Rate (%)",
            "range": [0, 70],
            "gridcolor": DARK_THEME["grid"],
        },
        xaxis={"title": None},
        height=300,
        margin={"t": 30, "b": 50, "l": 60, "r": 30},
        showlegend=False,
    )

    return to_html(fig)


def create_faction_elo_comparison(elo_data: EloData) -> str:
    """Create a grouped bar chart comparing faction performance.

    Args:
        elo_data: EloData object with ratings

    Returns:
        HTML string with embedded Plotly chart
    """
    faction_standings = elo_data.get_faction_standings()

    factions = list(faction_standings.keys())
    avg_ratings = [faction_standings[f]["avg_rating"] for f in factions]
    win_rates = [faction_standings[f]["win_rate"] * 100 for f in factions]
    colors = [FACTION_COLORS.get(f, DARK_THEME["text_secondary"]) for f in factions]

    fig = make_subplots(
        rows=1,
        cols=2,
        subplot_titles=("Average ELO Rating", "Win Rate (%)"),
        horizontal_spacing=0.15,
    )

    # Average rating bars
    fig.add_trace(
        go.Bar(
            x=[f.title() for f in factions],
            y=avg_ratings,
            marker_color=colors,
            name="Avg ELO",
            showlegend=False,
            hovertemplate="<b>%{x}</b><br>Avg ELO: %{y:.0f}<extra></extra>",
        ),
        row=1,
        col=1,
    )

    # Win rate bars
    fig.add_trace(
        go.Bar(
            x=[f.title() for f in factions],
            y=win_rates,
            marker_color=colors,
            name="Win Rate",
            showlegend=False,
            hovertemplate="<b>%{x}</b><br>Win Rate: %{y:.1f}%<extra></extra>",
        ),
        row=1,
        col=2,
    )

    # Add 1500 baseline to ELO chart
    fig.add_hline(y=1500, line_dash="dash", line_color=DARK_THEME["text_secondary"], line_width=1, row=1, col=1)

    # Add 50% baseline to win rate chart
    fig.add_hline(y=50, line_dash="dash", line_color=DARK_THEME["text_secondary"], line_width=1, row=1, col=2)

    fig.update_layout(
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        height=300,
        margin={"t": 50, "b": 50, "l": 60, "r": 30},
    )

    # Update axes
    fig.update_yaxes(gridcolor=DARK_THEME["grid"], row=1, col=1)
    fig.update_yaxes(gridcolor=DARK_THEME["grid"], row=1, col=2)

    # Style subplot titles
    for annotation in fig["layout"]["annotations"]:
        annotation["font"] = {"color": DARK_THEME["text_primary"]}

    return to_html(fig)


def create_combat_efficiency_chart(combat_stats: dict[str, dict[str, float]]) -> str:
    """Create a dual-axis bar chart for combat efficiency by faction.

    Args:
        combat_stats: Dict of faction -> {"trade_ratio": float, "face_damage": float}

    Returns:
        HTML string with embedded Plotly chart
    """
    if not combat_stats:
        return "<p>No combat efficiency data available</p>"

    factions = list(combat_stats.keys())
    labels = [f.title() for f in factions]
    trade_ratios = [combat_stats[f].get("trade_ratio", 1.0) for f in factions]
    face_damage = [combat_stats[f].get("face_damage", 15.0) for f in factions]
    colors = [FACTION_COLORS.get(f, DARK_THEME["text_secondary"]) for f in factions]

    fig = make_subplots(
        rows=1,
        cols=2,
        subplot_titles=("Trade Ratio", "Avg Face Damage per Game"),
        horizontal_spacing=0.15,
    )

    # Trade ratio bars
    fig.add_trace(
        go.Bar(
            x=labels,
            y=trade_ratios,
            marker_color=colors,
            name="Trade Ratio",
            showlegend=False,
            text=[f"{tr:.2f}" for tr in trade_ratios],
            textposition="outside",
            hovertemplate="<b>%{x}</b><br>Trade Ratio: %{y:.2f}<extra></extra>",
        ),
        row=1,
        col=1,
    )

    # Face damage bars
    fig.add_trace(
        go.Bar(
            x=labels,
            y=face_damage,
            marker_color=colors,
            name="Face Damage",
            showlegend=False,
            text=[f"{fd:.1f}" for fd in face_damage],
            textposition="outside",
            hovertemplate="<b>%{x}</b><br>Face Damage: %{y:.1f}<extra></extra>",
        ),
        row=1,
        col=2,
    )

    # Add 1.0 baseline to trade ratio
    fig.add_hline(
        y=1.0,
        line_dash="dash",
        line_color=DARK_THEME["text_secondary"],
        line_width=1,
        row=1,
        col=1,
    )

    fig.update_layout(
        paper_bgcolor=DARK_THEME["bg_primary"],
        plot_bgcolor=DARK_THEME["bg_secondary"],
        font={"color": DARK_THEME["text_primary"]},
        height=300,
        margin={"t": 50, "b": 50, "l": 60, "r": 30},
    )

    # Update axes
    fig.update_yaxes(gridcolor=DARK_THEME["grid"], row=1, col=1)
    fig.update_yaxes(gridcolor=DARK_THEME["grid"], row=1, col=2)

    # Style subplot titles
    for annotation in fig["layout"]["annotations"]:
        annotation["font"] = {"color": DARK_THEME["text_primary"]}

    return to_html(fig)
