"""Chart rendering for python-pptx."""

from __future__ import annotations

from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LEGEND_POSITION
from pptx.slide import Slide
from pptx.util import Inches, Pt

from pptx_mcp.engine.shapes import parse_hex_color
from pptx_mcp.models.slides import ChartElement, ChartType, Position
from pptx_mcp.utils.logging import get_logger

logger = get_logger("engine.charts")

CHART_TYPE_MAP: dict[ChartType, XL_CHART_TYPE] = {
    ChartType.BAR: XL_CHART_TYPE.BAR_CLUSTERED,
    ChartType.LINE: XL_CHART_TYPE.LINE_MARKERS,
    ChartType.PIE: XL_CHART_TYPE.PIE,
    ChartType.COLUMN: XL_CHART_TYPE.COLUMN_CLUSTERED,
    ChartType.AREA: XL_CHART_TYPE.AREA,
}


def default_chart_position() -> Position:
    """Default chart position centered on the slide."""
    return Position(left=1.5, top=2.0, width=10.0, height=5.0)


def add_chart_to_slide(
    slide: Slide,
    element: ChartElement,
    chart_colors: list[str] | None = None,
) -> None:
    """Add a chart to a slide.

    Args:
        slide: The python-pptx Slide object.
        element: Chart element definition.
        chart_colors: Optional list of hex colors for chart series.
    """
    pos = element.position or default_chart_position()
    xl_chart_type = CHART_TYPE_MAP.get(element.chart_type, XL_CHART_TYPE.COLUMN_CLUSTERED)

    chart_data = CategoryChartData()
    chart_data.categories = element.data.categories

    for series in element.data.series:
        chart_data.add_series(series.name, series.values)

    chart_frame = slide.shapes.add_chart(
        xl_chart_type,
        Inches(pos.left),
        Inches(pos.top),
        Inches(pos.width),
        Inches(pos.height),
        chart_data,
    )

    chart = chart_frame.chart

    if element.title:
        chart.has_title = True
        chart.chart_title.text_frame.paragraphs[0].text = element.title
        chart.chart_title.text_frame.paragraphs[0].font.size = Pt(14)

    if element.show_legend and element.chart_type != ChartType.PIE:
        chart.has_legend = True
        chart.legend.position = XL_LEGEND_POSITION.BOTTOM
        chart.legend.include_in_layout = False
    elif not element.show_legend:
        chart.has_legend = False

    if chart_colors and element.chart_type != ChartType.PIE:
        _apply_series_colors(chart, chart_colors)
    elif chart_colors and element.chart_type == ChartType.PIE:
        _apply_pie_colors(chart, chart_colors)

    if element.show_data_labels:
        for series in chart.series:
            series.has_data_labels = True
            series.data_labels.font.size = Pt(10)
            series.data_labels.show_value = True


def _apply_series_colors(chart: object, colors: list[str]) -> None:
    """Apply colors to chart series."""
    for i, series in enumerate(chart.series):  # type: ignore[attr-defined]
        if i < len(colors):
            series.format.fill.solid()
            series.format.fill.fore_color.rgb = parse_hex_color(colors[i])


def _apply_pie_colors(chart: object, colors: list[str]) -> None:
    """Apply colors to pie chart points."""
    try:
        series = chart.series[0]  # type: ignore[attr-defined]
        for i, point in enumerate(series.points):
            if i < len(colors):
                point.format.fill.solid()
                point.format.fill.fore_color.rgb = parse_hex_color(colors[i])
    except (IndexError, AttributeError) as e:
        logger.warning("Could not apply pie chart colors: %s", e)
