# VERSION: v1.11 - fire/ui_components/forecasting/forecast_backtest_widget.py (pre refactoring)
 
# RESP: Fornisce l'interfaccia utente per configurare, avviare e monitorare un'operazione di backtest di un modello di forecasting.
 
# DEPS: AppState, DataManager, ThemeManager
 
# ARCH_ROLE: feature
 
# LAYER: fire-app
 
  
 
from typing import Optional, Dict, Any
 
  
 
from PySide6.QtWidgets import (
 
    QWidget, QVBoxLayout, QPushButton,
 
    QSpinBox, QComboBox, QGroupBox, QProgressBar,
 
    QTextBrowser, QHBoxLayout, QFormLayout
 
)
 
from PySide6.QtCore import Qt, Signal, Slot
 
  
 
from fire.app_state import AppState
 
from fire.core.data.data_manager import DataManager
 
from fire.ui_components.theme_manager import ThemeManager
 
  
 
class ForecastBacktestWidget(QWidget):
 
    """
 
    Widget UI per configurare, eseguire e monitorare un backtest
 
    di un modello di forecasting. Delega la visualizzazione dei risultati.
 
    """
 
    backtest_requested = Signal(dict)
 
    results_ready = Signal(dict)
 
  
 
    def __init__(self, app_state: AppState, data_manager: DataManager, parent: Optional[QWidget] = None):
 
        super().__init__(parent)
 
        self.app_state = app_state
 
        self.data_manager = data_manager
 
        self._setup_ui()
 
        self._apply_theme()
 
        self._connect_signals()
 
        self.progress_group.setVisible(False)
 
        self.set_controls_enabled(True)
 
  
 
    def _setup_ui(self):
 
        main_layout = QVBoxLayout(self)
 
        config_group = QGroupBox("Configuration")
 
        form_layout = QFormLayout(config_group)
 
        self.model_combo = QComboBox()
 
        self.model_combo.addItem("TimesFM (Precision Focus)", "timesfm")
 
        self.model_combo.addItem("Chronos-2 (Universal Model)", "chronos-2")
 
        self.model_combo.addItem("Prophet (Trend & Direction)", "prophet")
 
        self.model_combo.setToolTip("Seleziona il modello di forecasting da usare per il backtest.")
 
  
 
        self.initial_window_spinbox = QSpinBox()
 
        self.initial_window_spinbox.setRange(30, 2000)
 
        self.initial_window_spinbox.setValue(252)
 
        self.initial_window_spinbox.setSingleStep(10)
 
        self.horizon_spinbox = QSpinBox()
 
        self.horizon_spinbox.setRange(1, 100)
 
        self.horizon_spinbox.setValue(10)
 
        self.horizon_spinbox.setToolTip("Il numero di giorni futuri da prevedere in ogni step.")
 
        self.run_backtest_button = QPushButton("Run Backtest")
 
  
 
        form_layout.addRow("Model:", self.model_combo)
 
        form_layout.addRow("Initial Training Window (days):", self.initial_window_spinbox)
 
        form_layout.addRow("Forecast Horizon (days):", self.horizon_spinbox)
 
        self.progress_group = QGroupBox("Backtest in Progress...")
 
        progress_layout = QVBoxLayout(self.progress_group)
 
        self.progress_bar = QProgressBar()
 
        self.progress_log = QTextBrowser(readOnly=True)
 
        self.progress_log.setMaximumHeight(150)
 
        self.cancel_button = QPushButton("Cancel")
 
        progress_layout.addWidget(self.progress_bar)
 
        progress_layout.addWidget(self.progress_log)
 
        progress_layout.addWidget(self.cancel_button, 0, Qt.AlignmentFlag.AlignRight)
 
  
 
        main_layout.addWidget(config_group)
 
        main_layout.addWidget(self.run_backtest_button)
 
        main_layout.addWidget(self.progress_group)
 
        main_layout.addStretch(1)
 
  
 
    def _apply_theme(self):
 
        """Applica lo stile standard centralizzato al pulsante di azione."""
 
        self.run_backtest_button.setStyleSheet(ThemeManager.get_action_button_style())
 
  
 
    def _connect_signals(self):
 
        self.run_backtest_button.clicked.connect(self._on_run_backtest_clicked)
 
  
 
    def set_controls_enabled(self, enabled: bool):
 
        self.model_combo.setEnabled(enabled)
 
        self.initial_window_spinbox.setEnabled(enabled)
 
        self.horizon_spinbox.setEnabled(enabled)
 
        self.run_backtest_button.setEnabled(enabled)
 
  
 
    @Slot()
 
    def _on_run_backtest_clicked(self):
 
        ticker = self.app_state.current_ticker
 
        if not ticker:
 
            self.app_state.log("Seleziona un ticker dalla watchlist prima di eseguire un backtest.", "WARNING")
 
            return
 
        params = {
 
            "model_name": self.model_combo.currentData(),
 
            "ticker": ticker,
 
            "start_date": self.app_state.global_start_date.toString("yyyy-MM-dd"),
 
            "end_date": self.app_state.global_end_date.toString("yyyy-MM-dd"),
 
            "initial_window": self.initial_window_spinbox.value(),
 
            "horizon": self.horizon_spinbox.value()
 
        }
 
        self.progress_group.setVisible(True)
 
        self.set_controls_enabled(False)
 
        self.progress_log.clear()
 
        self.backtest_requested.emit(params)
 
  
 
    @Slot(int, int)
 
    def on_progress_update(self, current_step: int, total_steps: int):
 
        self.progress_bar.setRange(0, total_steps)
 
        self.progress_bar.setValue(current_step)
 
        self.progress_bar.setFormat(f"Step {current_step} / {total_steps}")
 
  
 
    @Slot(str)
 
    def on_log_message(self, message: str):
 
        self.progress_log.append(message)
 
  
 
    @Slot(dict)
 
    def on_backtest_finished(self, results: Dict[str, Any]):
 
        self.progress_group.setVisible(False)
 
        self.set_controls_enabled(True)
 
        self.app_state.log("Backtest di forecasting completato. Risultati pronti.", "SUCCESS")
 
        self.results_ready.emit(results)
 
    @Slot()
 
    def on_backtest_error(self, error_msg: str):
 
        self.progress_group.setVisible(False)
 
        self.set_controls_enabled(True)
 
        self.app_state.log(f"Backtest di forecasting fallito: {error_msg}", "ERROR")