//! `fxt backtest` -- backtesting operations.

use anyhow::Result;
use clap::{Parser, Subcommand};
use colored::Colorize;
use serde::Serialize;

use crate::grpc::FoxhuntClient;
use crate::output::{self, HumanReadable, OutputFormat};

#[derive(Parser, Debug)]
pub struct BacktestCommand {
    #[command(subcommand)]
    action: BacktestAction,
}

#[derive(Subcommand, Debug)]
enum BacktestAction {
    /// Run a backtest
    Run {
        /// Strategy name or model ID
        #[arg(long)]
        strategy: String,
        /// Symbol to backtest
        #[arg(long)]
        symbol: String,
        /// Start date (YYYY-MM-DD)
        #[arg(long)]
        from: String,
        /// End date (YYYY-MM-DD)
        #[arg(long)]
        to: String,
    },
    /// Check backtest status
    Status {
        /// Backtest job ID
        job_id: String,
    },
    /// Show backtest results
    Results {
        /// Backtest job ID
        job_id: String,
    },
}

// ── Result types ────────────────────────────────────────────────────

#[derive(Serialize)]
struct BacktestRunResult {
    message: String,
    strategy: String,
    symbol: String,
    from: String,
    to: String,
    note: String,
}

impl HumanReadable for BacktestRunResult {
    fn print_human(&self) {
        println!("{}", "Backtest".bold().underline());
        println!("  Strategy: {}", self.strategy.cyan());
        println!("  Symbol:   {}", self.symbol);
        println!("  Period:   {} to {}", self.from, self.to);
        println!();
        println!("  {}", self.message.yellow());
        if !self.note.is_empty() {
            println!("  {}", self.note.dimmed());
        }
    }
}

#[derive(Serialize)]
struct BacktestStatusResult {
    job_id: String,
    message: String,
    note: String,
}

impl HumanReadable for BacktestStatusResult {
    fn print_human(&self) {
        println!("{}", "Backtest Status".bold().underline());
        println!("  Job ID: {}", self.job_id.cyan());
        println!("  {}", self.message.yellow());
        if !self.note.is_empty() {
            println!("  {}", self.note.dimmed());
        }
    }
}

#[derive(Serialize)]
struct BacktestResultsResult {
    job_id: String,
    message: String,
    note: String,
}

impl HumanReadable for BacktestResultsResult {
    fn print_human(&self) {
        println!("{}", "Backtest Results".bold().underline());
        println!("  Job ID: {}", self.job_id.cyan());
        println!("  {}", self.message.yellow());
        if !self.note.is_empty() {
            println!("  {}", self.note.dimmed());
        }
    }
}

// ── Execute ─────────────────────────────────────────────────────────

impl BacktestCommand {
    pub async fn execute(&self, _client: &FoxhuntClient, format: OutputFormat) -> Result<()> {
        // Backtesting RPCs are not yet defined in trading.proto.
        // These stubs describe what each subcommand will do once the
        // backtesting service exposes gRPC endpoints.

        match &self.action {
            BacktestAction::Run {
                strategy,
                symbol,
                from,
                to,
            } => {
                let result = BacktestRunResult {
                    message: "Backtest submission requires the backtesting gRPC service. \
                              Use the training pipeline directly for now."
                        .to_owned(),
                    strategy: strategy.clone(),
                    symbol: symbol.clone(),
                    from: from.clone(),
                    to: to.clone(),
                    note: "Pipeline: fxt train run --model <MODEL> --symbol <SYMBOL> \
                           (walk-forward with backtest windows)"
                        .to_owned(),
                };
                output::render(&result, format)?;
            }

            BacktestAction::Status { job_id } => {
                let result = BacktestStatusResult {
                    job_id: job_id.clone(),
                    message: "Backtest status tracking requires the backtesting gRPC service."
                        .to_owned(),
                    note: "Monitor training jobs: kubectl get jobs -n foxhunt -l app=training"
                        .to_owned(),
                };
                output::render(&result, format)?;
            }

            BacktestAction::Results { job_id } => {
                let result = BacktestResultsResult {
                    job_id: job_id.clone(),
                    message: "Backtest results require the backtesting gRPC service."
                        .to_owned(),
                    note: "View evaluation results: fxt model status <MODEL_ID>"
                        .to_owned(),
                };
                output::render(&result, format)?;
            }
        }

        Ok(())
    }
}
