from typing import Protocol, List, Union, Optional, Any
import pandas as pd


class ChartBuilderProtocol(Protocol):

    def bar(
        self,
        df: pd.DataFrame,
        x_axis: str,
        y_axes: Union[str, List[str]],
        title: Optional[str] = None,
        x_axis_title : Optional[str] = None,
        y_axis_title : Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def line(
        self,
        df: pd.DataFrame,
        x_axis: str,
        y_axes: Union[str, List[str]],
        title: Optional[str] = None,
        x_axis_title : Optional[str] = None,
        y_axis_title : Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def area(
        self,
        df: pd.DataFrame,
        x_axis: str,
        y_axes: Union[str, List[str]],
        title: Optional[str] = None,
        x_axis_title : Optional[str] = None,
        y_axis_title : Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def pie(
        self,
        df: pd.DataFrame,
        names: str,
        values: str,
        title: Optional[str] = None,
        x_axis_title : Optional[str] = None,
        y_axis_title : Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def histogram(
        self,
        df: pd.DataFrame,
        column: str,
        bins: int = 20,
        title: Optional[str] = None,
        x_axis_title : Optional[str] = None,
        y_axis_title : Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def combo(
        self,
        df: pd.DataFrame,
        x_axis: str,
        y1: str,
        y2: str,
        label1: Optional[str] = None,
        label2: Optional[str] = None,
        title: Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        ...

    def kpi(
        self,
        value: Union[int, float],
        title: Optional[str] = None,
        format: Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        """
        Render a KPI card displaying a single numeric value.

        Parameters
        ----------
        value : numeric
            The KPI value to display.
        title : optional str
            Title of the KPI card.
        format : optional str
            Format string (e.g. "${:,.0f}", "{:.2%}")
        theme : optional str
            Chart theme.
        """
        ...

    # ------------------------------
    # KPI - Comparison
    # ------------------------------

    def kpi_compare(
        self,
        current: Union[int, float],
        previous: Optional[Union[int, float]],
        change_pct: Optional[float],
        title: Optional[str] = None,
        format: Optional[str] = None,
        theme: Optional[str] = None,
    ) -> Any:
        """
        Render a KPI comparison card.

        Parameters
        ----------
        current : numeric
            Current period value.
        previous : numeric
            Previous period value.
        change_pct : float
            Percent change between periods.
        title : optional str
            Title of the KPI card.
        format : optional str
            Format string (e.g. "${:,.0f}")
        theme : optional str
            Chart theme.
        """
        ...

