//! Test Fixtures and Helpers for E2E Tests
//!
//! Provides reusable test data, helper functions, and utilities for E2E testing.

use std::collections::HashMap;
use fxt::proto::ml_training::{TrainingJobSummary, TrainingStatus};

/// Create a test training job with default values
pub fn create_test_job(
    job_id: &str,
    model_type: &str,
    status: TrainingStatus,
) -> TrainingJobSummary {
    create_test_job_with_times(
        job_id,
        model_type,
        status,
        chrono::Utc::now().timestamp(),
        0,
        0,
    )
}

/// Create a test training job with specific timestamps
pub fn create_test_job_with_times(
    job_id: &str,
    model_type: &str,
    status: TrainingStatus,
    created_at: i64,
    started_at: i64,
    completed_at: i64,
) -> TrainingJobSummary {
    TrainingJobSummary {
        job_id: job_id.to_string(),
        model_type: model_type.to_string(),
        status: status as i32,
        created_at,
        started_at,
        completed_at,
        description: format!("Test {} job for {}", model_type, job_id),
        final_loss: 0.123,
        best_validation_score: 0.456,
        tags: create_test_tags(),
    }
}

/// Create standard test tags
pub fn create_test_tags() -> HashMap<String, String> {
    let mut tags = HashMap::new();
    tags.insert("env".to_string(), "test".to_string());
    tags.insert("version".to_string(), "1.0".to_string());
    tags
}

/// Create a batch of test jobs for testing list/filter operations
pub fn create_test_job_batch() -> Vec<TrainingJobSummary> {
    let base_time = chrono::Utc::now().timestamp();
    vec![
        create_test_job_with_times(
            "train_tft_es_20251022_140000",
            "TFT",
            TrainingStatus::Running,
            base_time,
            base_time + 60,
            0,
        ),
        create_test_job_with_times(
            "train_dqn_nq_20251022_133000",
            "DQN",
            TrainingStatus::Completed,
            base_time - 3600,
            base_time - 3540,
            base_time - 3336,
        ),
        create_test_job_with_times(
            "train_ppo_es_20251022_130000",
            "PPO",
            TrainingStatus::Completed,
            base_time - 7200,
            base_time - 7140,
            base_time - 7133,
        ),
        create_test_job_with_times(
            "train_mamba2_6e_20251022_120000",
            "MAMBA_2",
            TrainingStatus::Failed,
            base_time - 14400,
            base_time - 14340,
            base_time - 14200,
        ),
        create_test_job_with_times(
            "train_tft_zn_20251022_110000",
            "TFT",
            TrainingStatus::Stopped,
            base_time - 18000,
            base_time - 17940,
            base_time - 17800,
        ),
    ]
}

/// Helper function to extract job IDs from job list
pub fn extract_job_ids(jobs: &[TrainingJobSummary]) -> Vec<String> {
    jobs.iter().map(|j| j.job_id.clone()).collect()
}

/// Helper function to filter jobs by status
pub fn filter_by_status(jobs: &[TrainingJobSummary], status: TrainingStatus) -> Vec<TrainingJobSummary> {
    jobs.iter()
        .filter(|j| j.status == status as i32)
        .cloned()
        .collect()
}

/// Helper function to filter jobs by model type
pub fn filter_by_model(jobs: &[TrainingJobSummary], model_type: &str) -> Vec<TrainingJobSummary> {
    jobs.iter()
        .filter(|j| j.model_type == model_type)
        .cloned()
        .collect()
}

/// Validate job structure
pub fn validate_job_structure(job: &TrainingJobSummary) -> bool {
    !job.job_id.is_empty()
        && !job.model_type.is_empty()
        && job.status >= 0
        && job.created_at > 0
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_test_job() {
        let job = create_test_job("test_1", "TFT", TrainingStatus::Pending);
        assert_eq!(job.job_id, "test_1");
        assert_eq!(job.model_type, "TFT");
        assert_eq!(job.status, TrainingStatus::Pending as i32);
    }

    #[test]
    fn test_create_test_job_batch() {
        let jobs = create_test_job_batch();
        assert_eq!(jobs.len(), 5);
        assert_eq!(jobs[0].model_type, "TFT");
        assert_eq!(jobs[1].model_type, "DQN");
        assert_eq!(jobs[2].model_type, "PPO");
    }

    #[test]
    fn test_filter_by_status() {
        let jobs = create_test_job_batch();
        let completed = filter_by_status(&jobs, TrainingStatus::Completed);
        assert_eq!(completed.len(), 2);
    }

    #[test]
    fn test_filter_by_model() {
        let jobs = create_test_job_batch();
        let tft_jobs = filter_by_model(&jobs, "TFT");
        assert_eq!(tft_jobs.len(), 2);
    }

    #[test]
    fn test_validate_job_structure() {
        let job = create_test_job("test_1", "TFT", TrainingStatus::Pending);
        assert!(validate_job_structure(&job));

        let invalid_job = TrainingJobSummary {
            job_id: "".to_string(),
            ..job
        };
        assert!(!validate_job_structure(&invalid_job));
    }

    #[test]
    fn test_extract_job_ids() {
        let jobs = create_test_job_batch();
        let ids = extract_job_ids(&jobs);
        assert_eq!(ids.len(), 5);
        assert!(ids.contains(&"train_tft_es_20251022_140000".to_string()));
    }
}
