import plotly.graph_objects as go
import pandas as pd
from dash import html
from layouts.components import create_metric_card

def create_equity_figure(result_dict):
    """
    Creates an equity curve figure comparing strategy performance against benchmark.
    """
    fig = go.Figure()

    fig.add_trace(go.Scatter(
        x=pd.to_datetime(result_dict['Dates']),
        y=result_dict['Equity Curve'],
        name='Strategy',
        line=dict(color='#2C7FB8', width=2)
    ))

    fig.add_trace(go.Scatter(
        x=pd.to_datetime(result_dict['Dates']),
        y=result_dict['Benchmark'],
        name='Benchmark',
        line=dict(color='#FC8D59', width=2)
    ))

    fig.update_layout(
        title={
            'text': "Equity Curve",
            'y': 0.95,
            'x': 0.5,
            'xanchor': 'center',
            'yanchor': 'top',
            'font': dict(size=16)
        },
        xaxis=dict(
            type="date",
            showgrid=True
        ),
        yaxis_title="Cumulative Return",
        template='plotly_white',
        height=500,
        hovermode='x unified',
        legend=dict(
            yanchor="top",
            y=0.99,
            xanchor="left",
            x=0.01,
            bgcolor='rgba(255, 255, 255, 0.8)'
        ),
        margin=dict(l=50, r=50, t=50, b=50)
    )

    return fig

def create_underwater_figure(result_dict):
    """
    Creates an underwater (drawdown) plot.
    """
    underwater = pd.Series(result_dict['Equity Curve']) - pd.Series(result_dict['Equity Curve']).cummax()
    fig = go.Figure()

    fig.add_trace(go.Scatter(
        x=pd.to_datetime(result_dict['Dates']),
        y=underwater,
        fill='tozeroy',
        name='Drawdown',
        line=dict(color='#2C7FB8', width=2),
        fillcolor='rgba(44, 127, 184, 0.3)'
    ))

    fig.update_layout(
        title={
            'text': "Drawdown",
            'y': 0.95,
            'x': 0.5,
            'xanchor': 'center',
            'yanchor': 'top',
            'font': dict(size=16)
        },
        xaxis=dict(
            type="date",
            showgrid=True
        ),
        yaxis_title="Drawdown",
        template='plotly_white',
        height=300,
        hovermode='x unified',
        showlegend=False,
        margin=dict(l=50, r=50, t=50, b=50)
    )

    return fig

def create_yearly_returns_figure(result_dict):
    """
    Creates a yearly returns comparison bar plot.
    """
    try:
        dates = pd.to_datetime(result_dict['Dates'])
        daily_returns = result_dict.get('Returns', None)

        if daily_returns is None:
            daily_returns = pd.Series(result_dict['Equity Curve'], index=dates).diff()

        daily_returns = pd.DataFrame({
            'equity': daily_returns,
            'benchmark': pd.Series(result_dict['Benchmark'], index=dates).diff()
        })

        yearly_returns = daily_returns.resample('Y').sum()

        fig = go.Figure()

        fig.add_trace(go.Bar(
            x=yearly_returns.index.year,
            y=yearly_returns['equity'],
            name='Strategy',
            marker_color='#2C7FB8'
        ))

        fig.add_trace(go.Bar(
            x=yearly_returns.index.year,
            y=yearly_returns['benchmark'],
            name='Benchmark',
            marker_color='#FC8D59'
        ))

        fig.add_hline(y=0, line_dash="dash", line_color="red", opacity=0.5)

        fig.update_layout(
            title={
                'text': "Yearly Returns",
                'y': 0.95,
                'x': 0.5,
                'xanchor': 'center',
                'yanchor': 'top',
                'font': dict(size=16)
            },
            yaxis_title="Returns",
            barmode='group',
            template='plotly_white',
            showlegend=True,
            legend=dict(
                orientation="h",
                y=1.1,
                x=0.5,
                xanchor="center",
                yanchor="bottom"
            ),
            height=300,
            margin=dict(l=50, r=50, t=80, b=50),
            bargap=0.2,
            bargroupgap=0.1
        )

        fig.update_xaxes(
            tickangle=0,
            dtick=1,
            tickfont=dict(size=12),
            range=[yearly_returns.index.year.min() - 0.5, yearly_returns.index.year.max() + 0.5]
        )

        fig.update_yaxes(
            title_font=dict(size=12),
            tickfont=dict(size=12),
            zeroline=True,
            zerolinewidth=1,
            zerolinecolor='red'
        )

        return fig

    except Exception as e:
        print(f"Error in create_yearly_returns_plot: {str(e)}")
        return go.Figure()

def create_metric_cards(result_dict):
    """
    Creates metric cards displaying strategy performance metrics.
    """
    metrics_data = [
        ('Return (Ann.)', f"{result_dict['Return (Ann.) [%]']:.2f}%", '#e3f2fd'),
        ('Sharpe Ratio', f"{result_dict['Sharpe Ratio']:.2f}", '#e3f2fd'),
        ('Calmar Ratio', f"{result_dict['Calmar Ratio']:.2f}", '#e3f2fd'),
        ('Max Drawdown', f"{result_dict['Max. Drawdown [%]']:.2f}%", '#e3f2fd'),
        ('Beta', f"{result_dict['Beta']:.3f}", '#e3f2fd')
    ]

    if 'Win Rate [%]' in result_dict:
        trading_metrics = [
            ('Win Rate', f"{result_dict['Win Rate [%]']:.2f}%", '#f1f8e9'),
            ('Avg Win', f"{result_dict['Avg Win [%]']:.2f}%", '#f1f8e9'),
            ('Avg Loss', f"{result_dict['Avg Loss [%]']:.2f}%", '#f1f8e9'),
            ('Number of Trades', f"{result_dict['Number of Trades']}", '#f1f8e9'),
            ('Long Duration', f"{result_dict['Long Duration [%]']:.2f}%", '#fff3e0'),
            ('Short Duration', f"{result_dict['Short Duration [%]']:.2f}%", '#fff3e0'),
            ('Holding Time [%]', f"{result_dict['Turnover [%]']:.2f}%", '#fff3e0'),
            ('Holding Time', f"{result_dict['Turnover Period']:.2f}", '#fff3e0')
        ]
        metrics_data.extend(trading_metrics)

    metrics_style = {
        'padding': '12px',
        'backgroundColor': 'white',
        'borderRadius': '8px',
        'boxShadow': '0 1px 3px rgba(0,0,0,0.1)',
        'textAlign': 'center',
        'minWidth': '150px',
        'transition': 'transform 0.2s ease-in-out'
    }

    metric_cards = []
    for label, value, bg_color in metrics_data:
        current_style = metrics_style.copy()
        current_style['backgroundColor'] = bg_color
        metric_cards.append(
            html.Div([
                html.Div(label, style={
                    'fontSize': '13px',
                    'color': '#555',
                    'fontWeight': '500',
                    'marginBottom': '4px',
                    'whiteSpace': 'nowrap'
                }),
                html.Div(value, style={
                    'fontSize': '15px',
                    'fontWeight': 'bold',
                    'color': '#2c3e50'
                })
            ], style=current_style)
        )

    return metric_cards

def create_strategy_header(mode, current_selection, start_date, end_date, click_data=None):
    """
    Creates the strategy header with parameters and period information.
    """
    if mode == 'aggregative' and current_selection:
        strategy_buttons = [
            html.Div([
                html.Span(
                    f"({s['window']}, {s['threshold']:.2f})",
                    style={'marginRight': '4px'}
                ),
                html.Button(
                    "×",
                    id={'type': 'remove-strategy', 'index': i},
                    n_clicks=0,
                    style={
                        'border': 'none',
                        'background': 'transparent',
                        'color': '#666',
                        'fontSize': '18px',
                        'fontWeight': 'bold',
                        'cursor': 'pointer',
                        'padding': '2px 8px',
                        'verticalAlign': 'middle',
                        'lineHeight': '1',
                        'transition': 'color 0.2s',
                        'margin': '0 2px',
                        'borderRadius': '50%',
                    }
                )
            ], style={
                'display': 'inline-flex',
                'alignItems': 'center',
                'margin': '2px 4px',
                'padding': '4px 8px',
                'backgroundColor': '#f0f0f0',
                'border': '1px solid #ddd',
                'borderRadius': '16px',
                'fontSize': '14px'
            }) for i, s in enumerate(current_selection)
        ]

        return html.Div([
            html.Div("Combined Strategy Details",
                     style={'fontSize': '18px', 'fontWeight': 'bold', 'marginBottom': '8px'}),
            html.Div([
                html.Span("Parameters: ", style={'marginRight': '8px'}),
                html.Div(strategy_buttons, style={'display': 'inline-block'})
            ], style={'marginBottom': '8px'}),
            html.Div(
                f"Period: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}"
                if start_date and end_date else ""
            )
        ])

    elif click_data:
        window = click_data['points'][0]['x']
        threshold = click_data['points'][0]['y']
        return html.Div([
            html.Div("Strategy Details",
                     style={'fontSize': '18px', 'fontWeight': 'bold', 'marginBottom': '8px'}),
            html.Div([
                html.Span("Parameters: ", style={'marginRight': '8px'}),
                html.Span(f"({window}, {threshold:.2f})")
            ], style={'marginBottom': '8px'}),
            html.Div(
                f"Period: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}"
                if start_date and end_date else ""
            )
        ])

    return html.Div("Click on heatmap to see strategy details")

def create_error_message(error_type, start_date=None, end_date=None, error_message=None):
    """
    Creates error message displays.
    """
    if error_type == "no_trade":
        return html.Div([
            html.Div("No Trade Data",
                     style={'fontSize': '18px', 'fontWeight': 'bold', 'marginBottom': '8px'}),
            html.Div(
                f"There is no trade from {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}"
            )
        ])
    else:
        return html.Div([
            html.Div("Error",
                     style={'fontSize': '18px', 'fontWeight': 'bold', 'marginBottom': '8px'}),
            html.Div(f"An error occurred: {error_message}")
        ])

def create_metrics_component(result_dict):
    """Create metrics component with grid layout using create_metric_card."""
    if result_dict is None or not isinstance(result_dict, dict):
        return html.Div()  # Just return an empty div without styling

    try:
        # Define metrics in a grid-friendly format
        metrics_grid = [
            [
                ('Return (Ann.)', f"{result_dict.get('Return (Ann.) [%]', 0):.2f}%"),
                ('Sharpe Ratio', f"{result_dict.get('Sharpe Ratio', 0):.2f}")
            ],
            [
                ('Calmar Ratio', f"{result_dict.get('Calmar Ratio', 0):.2f}"),
                ('Max Drawdown', f"{result_dict.get('Max. Drawdown [%]', 0):.2f}%")
            ],
            [
                ('Beta', f"{result_dict.get('Beta', 0):.3f}"),
                (None, None)
            ]
        ]

        # Create grid layout
        grid_rows = []
        for row in metrics_grid:
            row_cells = []
            for label, value in row:
                if label is not None:
                    cell = create_metric_card(label, value, '#e3f2fd')
                    row_cells.append(cell)

            grid_rows.append(html.Div(row_cells, style={
                'display': 'flex',
                'justifyContent': 'flex-start',
                'gap': '10px',
                'marginBottom': '10px'
            }))

        return html.Div(grid_rows)  # Remove the container styling

    except Exception as e:
        print(f"Error in create_metrics_component: {str(e)}")
        return html.Div()  # Return empty div without styling