"""Plotly chart rendering helpers."""

from __future__ import annotations

from pathlib import Path
from typing import Iterable, List, Optional


class PlotlyRenderError(RuntimeError):
    """Raised when Plotly rendering fails."""


def render_chart(
    csv_path: Path,
    *,
    chart_type: str,
    x_col: str,
    y_col: Optional[str] = None,
    series_cols: Optional[Iterable[str]] = None,
    title: Optional[str] = None,
    output_path: Optional[Path] = None,
    width: int = 900,
    height: int = 500,
) -> Path:
    """
    Render a Plotly chart from a CSV and write it to an image file.
    """
    pd, px = _load_plotly()

    if not csv_path.exists():
        raise PlotlyRenderError(f"CSV not found: {csv_path}")

    chart = _normalize_chart_type(chart_type)
    df = pd.read_csv(csv_path)

    series = _combine_series(y_col, series_cols)
    if chart == "PIE":
        if not x_col or not series:
            raise PlotlyRenderError("Pie charts require --x and --y columns.")
        fig = px.pie(df, names=x_col, values=series[0], title=title)
    elif chart == "SCATTER":
        if not x_col or not series:
            raise PlotlyRenderError("Scatter charts require --x and --y columns.")
        if len(series) > 1:
            raise PlotlyRenderError("Scatter charts support a single --y column.")
        fig = px.scatter(df, x=x_col, y=series[0], title=title)
    elif chart == "LINE":
        if not x_col or not series:
            raise PlotlyRenderError("Line charts require --x and --y columns.")
        fig = px.line(df, x=x_col, y=series, title=title)
    elif chart == "AREA":
        if not x_col or not series:
            raise PlotlyRenderError("Area charts require --x and --y columns.")
        fig = px.area(df, x=x_col, y=series, title=title)
    elif chart in {"BAR", "COLUMN"}:
        if not x_col or not series:
            raise PlotlyRenderError("Bar charts require --x and --y columns.")
        fig = px.bar(df, x=x_col, y=series, title=title)
    else:
        raise PlotlyRenderError("Unsupported chart type.")

    fig.update_layout(width=width, height=height)

    output = output_path or Path("chart.png")
    output.parent.mkdir(parents=True, exist_ok=True)
    try:
        fig.write_image(str(output))
    except Exception as exc:  # pragma: no cover - depends on kaleido
        raise PlotlyRenderError(
            "Plotly image export failed. Install kaleido: pip install g-gremlin[visualize]"
        ) from exc
    return output


def _load_plotly():
    try:
        import pandas as pd
        import plotly.express as px
    except Exception as exc:  # pragma: no cover - optional dependency
        raise PlotlyRenderError(
            "Plotly rendering requires optional dependencies. Install with: pip install g-gremlin[visualize]"
        ) from exc
    return pd, px


def _normalize_chart_type(value: str) -> str:
    if not value:
        return ""
    return value.strip().upper()


def _combine_series(y_col: Optional[str], series_cols: Optional[Iterable[str]]) -> List[str]:
    series: List[str] = []
    if y_col:
        series.append(y_col)
    if series_cols:
        for item in series_cols:
            if item and item not in series:
                series.append(item)
    return series


__all__ = ["PlotlyRenderError", "render_chart"]
