"""
Plot Components for Indicator and Strategy Visualization

This module provides dataclass-based components for building chart visualizations.
Each component represents a different chart element (line, scatter, bar, etc.).

Usage:
    from sixtysix_core import Line, Scatter, Bar, Fill

    def plot(self, df):
        sma = df['close'].rolling(20).mean()
        return [
            Line(y=sma, color='#2962ff', line_width=2),
            HLine(y=0, color='#888888', line_dash='dashed'),
        ]
"""

from __future__ import annotations
from dataclasses import dataclass
from typing import List, Literal, Optional, Union
import pandas as pd
import numpy as np


# Type aliases for data that can be passed to plot components
SeriesLike = Union[pd.Series, List, np.ndarray]
ColorLike = Union[str, List[str], pd.Series]  # Single color or per-point colors

# Literal types for constrained string options
LineDash = Literal['solid', 'dashed', 'dotted']
ScatterShape = Literal['circle', 'square', 'diamond', 'triangle_up', 'triangle_down']
PositionMode = Literal['right_edge', 'fixed', 'left_edge']
TextAlign = Literal['left', 'center', 'right']
TextBaseline = Literal['top', 'middle', 'bottom']


@dataclass
class Line:
    """
    Line plot component.

    Example:
        sma = df['close'].rolling(20).mean()
        Line(y=sma, color='#2962ff', line_width=2)
    """
    y: SeriesLike
    color: Optional[ColorLike] = None
    line_width: Optional[float] = None
    line_dash: Optional[LineDash] = None
    alpha: Optional[float] = None
    legend: Optional[str] = None


@dataclass
class Scatter:
    """
    Scatter/point plot component.

    Example:
        Scatter(y=signals, color='#22c55e', shape='triangle_up', size=10)
    """
    y: SeriesLike
    x: Optional[SeriesLike] = None
    color: Optional[ColorLike] = None
    size: Optional[Union[int, SeriesLike]] = None
    shape: Optional[ScatterShape] = None
    alpha: Optional[float] = None
    legend: Optional[str] = None


@dataclass
class Bar:
    """
    Vertical bar plot component.

    Example:
        colors = ['#22c55e' if v > 0 else '#ef4444' for v in histogram]
        Bar(y=histogram, color=colors)
    """
    y: SeriesLike
    color: Optional[ColorLike] = None
    alpha: Optional[float] = None
    legend: Optional[str] = None


@dataclass
class HBar:
    """
    Horizontal bar plot component (for volume profile, etc.).

    Example:
        HBar(y=price_levels, width=volumes, color='#9333ea', position_mode='right_edge')
    """
    y: SeriesLike
    width: SeriesLike
    color: Optional[ColorLike] = None
    alpha: Optional[float] = None
    line_color: Optional[str] = None
    line_alpha: Optional[float] = None
    position_mode: Optional[PositionMode] = None
    legend: Optional[str] = None


@dataclass
class HLine:
    """
    Horizontal line at a fixed y value.

    Example:
        HLine(y=70, color='#ef4444', line_dash='dashed')  # RSI overbought
    """
    y: float
    color: Optional[str] = None
    line_width: Optional[int] = None
    line_dash: Optional[LineDash] = None
    alpha: Optional[float] = None


@dataclass
class Fill:
    """
    Fill area between two y arrays.

    Example:
        Fill(y1=upper_band, y2=lower_band, color='#3b82f6', alpha=0.1)
    """
    y1: SeriesLike
    y2: SeriesLike
    color: Optional[ColorLike] = None  # Can be per-point for conditional fills
    alpha: Optional[float] = None


@dataclass
class Segment:
    """
    Line segments from (x0, y0) to (x1, y1).

    Example:
        Segment(x0=start_times, y0=start_prices, x1=end_times, y1=end_prices, color='#26a69a')
    """
    x0: SeriesLike
    y0: SeriesLike
    x1: SeriesLike
    y1: SeriesLike
    color: Optional[ColorLike] = None
    line_width: Optional[int] = None
    line_dash: Optional[LineDash] = None
    alpha: Optional[float] = None


@dataclass
class Marker:
    """
    Buy/sell signal markers (triangles).

    Example:
        Marker(y=prices, signal_type=types, buy_color='#22c55e', sell_color='#ef4444')
    """
    y: SeriesLike
    signal_type: SeriesLike  # 'buy' or 'sell' per point
    x: Optional[SeriesLike] = None
    buy_color: Optional[str] = None
    sell_color: Optional[str] = None
    size: Optional[int] = None
    alpha: Optional[float] = None


@dataclass
class SignalPlot:
    """
    Enhanced buy/sell signals with connecting lines to candles.

    Example:
        SignalPlot(y=prices, signal_type=types, buy_color='#22c55e', sell_color='#ef4444')
    """
    y: SeriesLike
    signal_type: SeriesLike
    x: Optional[SeriesLike] = None
    buy_color: Optional[str] = None
    sell_color: Optional[str] = None
    size: Optional[int] = None
    line_width: Optional[int] = None
    alpha: Optional[float] = None


@dataclass
class Label:
    """
    Text annotations at specific positions.

    Example:
        Label(y=prices, text=labels, color='#ffffff', font_size='10px')
    """
    y: SeriesLike
    text: SeriesLike  # Text content per point
    x: Optional[SeriesLike] = None
    color: Optional[ColorLike] = None
    font_size: Optional[str] = None
    text_align: Optional[TextAlign] = None
    text_baseline: Optional[TextBaseline] = None
    x_offset: Optional[int] = None
    y_offset: Optional[int] = None
    alpha: Optional[float] = None


# Type alias for all plot components
PlotComponent = Union[Line, Scatter, Bar, HBar, HLine, Fill, Segment, Marker, SignalPlot, Label]


@dataclass
class Panel:
    """
    Oscillator/indicator panel below the main chart.

    Example:
        Panel(
            name='MACD',
            height=120,
            components=[
                Line(y=macd_line, color='#3b82f6', legend='MACD'),
                Line(y=signal_line, color='#f97316', legend='Signal'),
                Bar(y=histogram, color=hist_colors, legend='Histogram'),
                HLine(y=0, color='#888888', line_dash='dotted'),
            ]
        )
    """
    name: str
    components: List[PlotComponent]
    height: int = 120  # Height in pixels


@dataclass
class PlotResult:
    """
    Combined plot result with overlay components and oscillator panels.

    Strategies can return either:
    - List[PlotComponent] for overlay-only (backwards compatible)
    - PlotResult for overlay + oscillator panels

    Example:
        def plot(self, df):
            return PlotResult(
                overlay=[
                    Segment(...),  # Zigzag
                    Marker(...),   # Buy/sell signals
                ],
                panels=[
                    Panel(name='MACD', components=[...]),
                    Panel(name='RSI', components=[...]),
                ]
            )
    """
    overlay: List[PlotComponent] = None
    panels: List[Panel] = None

    def __post_init__(self):
        if self.overlay is None:
            self.overlay = []
        if self.panels is None:
            self.panels = []


__all__ = [
    # Type aliases
    'SeriesLike',
    'ColorLike',
    'PlotComponent',
    # Literal types
    'LineDash',
    'ScatterShape',
    'PositionMode',
    'TextAlign',
    'TextBaseline',
    # Components
    'Line',
    'Scatter',
    'Bar',
    'HBar',
    'HLine',
    'Fill',
    'Segment',
    'Marker',
    'SignalPlot',
    'Label',
    # Panel system
    'Panel',
    'PlotResult',
]
