# callbacks/strategy/helpers.py
from dash import html
import pandas as pd
from models.backtest import backtest, combine_strategies
from utils.helpers import get_default_date_range
from .constants import get_base_style
from .components import (
    create_equity_figure,
    create_underwater_figure,
    create_yearly_returns_figure,
    create_metric_cards,
    create_strategy_header,
    create_error_message
)

def get_default_outputs():
    """Return default outputs when no interaction has occurred."""
    return [], {}, {}, {}, html.Div("Click on heatmap to see strategy details"), None, None, [], {'display': 'none'}, ''

def handle_mode_change(trigger_id, mode, current_selection):
    """Handle mode changes and clear selection."""
    if trigger_id == 'strategy-clear-selection' or mode == 'single':
        current_selection = []

    selected_count = f'Selected strategies: {len(current_selection)}' if mode == 'aggregative' else ''
    from app import full_data
    default_start, default_end = get_default_date_range(full_data)

    return [], {}, {}, {}, html.Div("Click on heatmap to see strategy details"), \
        default_start, default_end, current_selection, get_base_style(mode), selected_count

def get_date_range(trigger_id, start_date, end_date):
    """Handle date range reset and processing."""
    if trigger_id == 'reset-date-range':
        from app import full_data
        start_date, end_date = get_default_date_range(full_data)

    if start_date and end_date:
        start_date = pd.to_datetime(start_date)
        end_date = pd.to_datetime(end_date)

    return start_date, end_date

def get_filtered_data(start_date, end_date):
    """Get data filtered by date range."""
    from app import full_data
    if start_date and end_date:
        return full_data[start_date:end_date]
    return full_data

def update_strategy_selection(mode, trigger_id, click_data, current_selection):
    """Update strategy selection based on mode and user interaction."""
    if mode == 'aggregative' and trigger_id == 'combined-heatmap' and click_data:
        new_strategy = {
            'window': click_data['points'][0]['x'],
            'threshold': click_data['points'][0]['y']
        }
        if new_strategy not in current_selection:
            return current_selection + [new_strategy]
    elif mode == 'single':
        return []
    return current_selection

def get_backtest_results(mode, current_selection, data, click_data, time_factor, commission):
    """Get backtest results based on mode and selected strategies."""
    if mode == 'single' or not current_selection:
        window = click_data['points'][0]['x']
        threshold = click_data['points'][0]['y']
        return backtest(data, window, threshold, time_factor, commission, 'full_report')
    return combine_strategies(data, current_selection, time_factor, commission)

def create_output_components(result_dict, mode, current_selection, start_date, end_date, click_data):
    """Create all visual components."""
    metric_cards = create_metric_cards(result_dict)
    equity_fig = create_equity_figure(result_dict)
    underwater_fig = create_underwater_figure(result_dict)
    yearly_returns_fig = create_yearly_returns_figure(result_dict)
    header_text = create_strategy_header(mode, current_selection, start_date, end_date, click_data)

    base_style = get_base_style(mode)
    selected_count = f'Selected strategies: {len(current_selection)}' if mode == 'aggregative' else ''

    return (metric_cards, equity_fig, underwater_fig, yearly_returns_fig,
            header_text, start_date, end_date, current_selection,
            base_style, selected_count)

def handle_error(error_type, start_date, end_date, current_selection, mode, error_message=None):
    """Handle various error cases."""
    base_style = get_base_style(mode)
    selected_count = f'Selected strategies: {len(current_selection)}' if mode == 'aggregative' else ''

    if error_type == "zero_division":
        error_msg = create_error_message("no_trade", start_date, end_date)
    else:
        error_msg = create_error_message("error", error_message=error_message)

    return [], {}, {}, {}, error_msg, start_date, end_date, current_selection, base_style, selected_count