import logging
from abc import abstractmethod, ABC
from typing import Optional, Tuple, List

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.figure import Figure


class ChartingAPI(ABC):
    """
    API for creating financial charts and visualizations.

    Provides methods to create candlestick charts, add technical indicator panels,
    and build custom visualizations. All figures are automatically captured and
    returned to the client as images.

    Basic workflow:
    1. Create a chart with plot_ohlc() → returns Figure and Axes
    2. Optionally overlay indicators on the main axes (e.g., moving averages)
    3. Optionally add indicator panels below with add_indicator_panel()
    4. Figures are automatically captured (no need to save manually)
    """

    @abstractmethod
    def plot_ohlc(
        self,
        df: pd.DataFrame,
        title: Optional[str] = None,
        volume: bool = False,
        style: str = "charles",
        figsize: Tuple[int, int] = (12, 8),
        **kwargs
    ) -> Tuple[Figure, plt.Axes]:
        """
        Create a candlestick chart from OHLC data.

        Args:
            df: DataFrame with OHLC data. Required columns: open, high, low, close.
               Column names are case-insensitive.
            title: Chart title (optional)
            volume: If True, shows volume bars below the candlesticks (requires 'volume' column)
            style: Visual style for the chart. Available styles:
                  "charles" (default), "binance", "blueskies", "brasil", "checkers",
                  "classic", "mike", "nightclouds", "sas", "starsandstripes", "yahoo"
            figsize: Figure size as (width, height) in inches. Default: (12, 8)
            **kwargs: Additional styling arguments

        Returns:
            Tuple of (Figure, Axes):
            - Figure: matplotlib Figure object
            - Axes: Main candlestick axes (use for overlaying indicators)

        Examples:
            # Basic chart
            fig, ax = api.plot_ohlc(df)

            # With volume and title
            fig, ax = api.plot_ohlc(
                df,
                title="BTC/USDT 1H",
                volume=True,
                style="binance"
            )

            # Overlay moving average
            # NOTE: mplfinance uses integer x-positions (0..N-1) internally,
            # so overlays must use range(len(df)), not df.index.
            fig, ax = api.plot_ohlc(df)
            ax.plot(range(len(df)), df['sma_20'], label="SMA 20", color="blue")
            ax.legend()
        """
        pass

    @abstractmethod
    def add_indicator_panel(
        self,
        fig: Figure,
        df: pd.DataFrame,
        columns: Optional[List[str]] = None,
        ylabel: Optional[str] = None,
        height_ratio: float = 0.3,
        ylim: Optional[Tuple[float, float]] = None,
        **kwargs
    ) -> plt.Axes:
        """
        Add an indicator panel below the chart with time-aligned x-axis.

        Use this to display indicators that should be shown separately from the
        price chart (e.g., RSI, MACD, volume).

        Args:
            fig: Figure object from plot_ohlc()
            df: DataFrame with indicator data (must have same index as OHLC data)
            columns: Column names to plot. If None, plots all numeric columns.
            ylabel: Y-axis label (e.g., "RSI", "MACD")
            height_ratio: Panel height relative to main chart (default: 0.3 = 30%)
            ylim: Y-axis limits as (min, max). If None, auto-scales.
            **kwargs: Line styling options (color, linewidth, linestyle, alpha)

        Returns:
            Axes object for the new panel (use for further customization)

        Examples:
            # Add RSI panel with reference lines
            fig, ax = api.plot_ohlc(df)
            rsi_ax = api.add_indicator_panel(
                fig, df,
                columns=["rsi"],
                ylabel="RSI",
                ylim=(0, 100)
            )
            rsi_ax.axhline(30, color='green', linestyle='--', alpha=0.5)
            rsi_ax.axhline(70, color='red', linestyle='--', alpha=0.5)

            # Add MACD panel
            fig, ax = api.plot_ohlc(df)
            api.add_indicator_panel(
                fig, df,
                columns=["macd", "macd_signal"],
                ylabel="MACD"
            )
        """
        pass

    @abstractmethod
    def create_figure(
        self,
        figsize: Tuple[int, int] = (12, 8),
        style: str = "charles"
    ) -> Tuple[Figure, plt.Axes]:
        """
        Create a styled figure for custom visualizations.

        Use this when you want to create charts other than candlesticks
        (e.g., histograms, scatter plots, heatmaps).

        Args:
            figsize: Figure size as (width, height) in inches. Default: (12, 8)
            style: Style name for consistent theming. Default: "charles"

        Returns:
            Tuple of (Figure, Axes) ready for plotting

        Examples:
            # Histogram
            fig, ax = api.create_figure()
            ax.hist(returns, bins=50)
            ax.set_title("Return Distribution")

            # Heatmap
            fig, ax = api.create_figure(figsize=(10, 10))
            import seaborn as sns
            sns.heatmap(correlation_matrix, ax=ax)
            ax.set_title("Correlation Matrix")
        """
        pass
