"""Reusable Plotly chart builders for results visualization."""

import plotly.express as px
import plotly.graph_objects as go


def channel_contribution_waterfall(contributions: dict[str, float]) -> go.Figure:
    """Waterfall chart showing each channel's contribution to the target metric."""
    channels = list(contributions.keys())
    values = list(contributions.values())

    fig = go.Figure(
        go.Waterfall(
            name="Contribution",
            orientation="v",
            x=channels,
            y=values,
            connector={"line": {"color": "rgb(63, 63, 63)"}},
            textposition="outside",
            text=[f"${v:,.0f}" for v in values],
        )
    )
    fig.update_layout(
        title="Channel Contributions",
        yaxis_title="Contribution ($)",
        showlegend=False,
        height=400,
    )
    return fig


def roas_bar_chart(
    roas: dict[str, float],
    roas_ci: dict[str, tuple[float, float]] | None = None,
) -> go.Figure:
    """Bar chart of ROAS per channel with optional credible intervals."""
    channels = list(roas.keys())
    values = list(roas.values())

    fig = go.Figure()

    error_y = None
    if roas_ci:
        error_y = {
            "type": "data",
            "symmetric": False,
            "array": [roas_ci[c][1] - roas[c] for c in channels],
            "arrayminus": [roas[c] - roas_ci[c][0] for c in channels],
        }

    fig.add_trace(
        go.Bar(
            x=channels,
            y=values,
            error_y=error_y,
            text=[f"{v:.2f}x" for v in values],
            textposition="outside",
            marker_color="steelblue",
        )
    )

    fig.add_hline(y=1.0, line_dash="dash", line_color="red", annotation_text="Break-even")
    fig.update_layout(
        title="Return on Ad Spend (ROAS) by Channel",
        yaxis_title="ROAS",
        showlegend=False,
        height=400,
    )
    return fig


def allocation_pie_charts(
    current: dict[str, float],
    optimal: dict[str, float],
) -> tuple[go.Figure, go.Figure]:
    """Before/after pie charts for budget allocation."""
    fig_current = px.pie(
        names=list(current.keys()),
        values=list(current.values()),
        title="Current Allocation",
        hole=0.3,
    )
    fig_current.update_layout(height=350)

    fig_optimal = px.pie(
        names=list(optimal.keys()),
        values=list(optimal.values()),
        title="Optimal Allocation",
        hole=0.3,
    )
    fig_optimal.update_layout(height=350)

    return fig_current, fig_optimal


def saturation_curves(
    channel_data: dict[str, dict],
) -> go.Figure:
    """Plot saturation curves for each channel (spend vs marginal response)."""
    fig = go.Figure()

    colors = px.colors.qualitative.Set2
    for i, (channel, data) in enumerate(channel_data.items()):
        fig.add_trace(
            go.Scatter(
                x=data["spend"],
                y=data["response"],
                mode="lines",
                name=channel,
                line={"color": colors[i % len(colors)]},
            )
        )

    fig.update_layout(
        title="Channel Saturation Curves",
        xaxis_title="Weekly Spend ($)",
        yaxis_title="Marginal Response",
        height=400,
    )
    return fig
