//! Performance benchmarks for the tvai library

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::time::Duration;
use tempfile::TempDir;
use tvai::*;

/// Benchmark GPU detection performance
fn benchmark_gpu_detection(c: &mut Criterion) {
    c.bench_function("gpu_detection", |b| {
        b.iter(|| {
            let gpu_info = black_box(GpuManager::detect_detailed_gpu_info());
            black_box(gpu_info);
        })
    });
}

/// Benchmark settings management performance
fn benchmark_settings_management(c: &mut Criterion) {
    let temp_dir = TempDir::new().expect("Should create temp dir");
    let config_path = temp_dir.path().join("bench_config.toml");
    
    c.bench_function("settings_save_load", |b| {
        b.iter(|| {
            let settings_manager = SettingsManager::with_config_file(&config_path);
            
            // Update settings
            settings_manager.set_default_use_gpu(true).expect("Should update");
            settings_manager.set_max_concurrent_jobs(2).expect("Should update");
            
            // Save and load
            settings_manager.save_to_file().expect("Should save");
            let loaded_settings = settings_manager.get_settings();
            
            black_box(loaded_settings);
        })
    });
}

/// Benchmark preset management performance
fn benchmark_preset_management(c: &mut Criterion) {
    c.bench_function("preset_lookup", |b| {
        b.iter(|| {
            let presets = global_presets();
            let preset_manager = presets.lock().unwrap();
            
            // Lookup various presets
            let video_preset = preset_manager.get_video_preset("general_2x");
            let image_preset = preset_manager.get_image_preset("photo_2x");
            
            black_box((video_preset, image_preset));
        })
    });
    
    c.bench_function("preset_listing", |b| {
        b.iter(|| {
            let presets = global_presets();
            let preset_manager = presets.lock().unwrap();
            
            let video_presets = preset_manager.list_video_presets();
            let image_presets = preset_manager.list_image_presets();
            
            black_box((video_presets, image_presets));
        })
    });
}

/// Benchmark temporary file management
fn benchmark_temp_file_management(c: &mut Criterion) {
    let temp_dir = TempDir::new().expect("Should create temp dir");
    
    c.bench_function("temp_file_creation", |b| {
        b.iter(|| {
            let mut temp_manager = TempFileManager::new(Some(temp_dir.path())).expect("Should create");
            
            // Create multiple temp paths
            for i in 0..10 {
                let path = temp_manager.create_temp_path(&format!("op_{}", i), "test.txt");
                black_box(path);
            }
            
            black_box(temp_manager);
        })
    });
    
    c.bench_function("temp_file_cleanup", |b| {
        b.iter(|| {
            let mut temp_manager = TempFileManager::new(Some(temp_dir.path())).expect("Should create");
            
            // Create temp paths
            for i in 0..10 {
                temp_manager.create_temp_path(&format!("op_{}", i), "test.txt");
            }
            
            // Cleanup
            temp_manager.cleanup_all().expect("Should cleanup");
            
            black_box(temp_manager);
        })
    });
}

/// Benchmark performance monitoring
fn benchmark_performance_monitoring(c: &mut Criterion) {
    c.bench_function("performance_monitoring", |b| {
        b.iter(|| {
            let settings = optimize_for_system();
            let mut monitor = PerformanceMonitor::new(settings);

            // Simulate operation (without async for benchmark)
            let operation_monitor = monitor.start_operation("benchmark", 100.0);

            // Simulate work with thread sleep instead of async
            std::thread::sleep(Duration::from_micros(100));

            let metrics = operation_monitor.finish(200.0);
            monitor.record_metrics(metrics);

            let summary = monitor.get_summary();
            black_box(summary);
        })
    });
}

/// Benchmark parameter validation
fn benchmark_parameter_validation(c: &mut Criterion) {
    c.bench_function("video_params_validation", |b| {
        b.iter(|| {
            let params = VideoUpscaleParams {
                scale_factor: 2.0,
                model: UpscaleModel::Iris3,
                compression: 0.0,
                blend: 0.1,
                quality_preset: QualityPreset::HighQuality,
            };
            
            // Simulate validation (would be done in processor)
            let valid = params.scale_factor > 0.0 && params.scale_factor <= 4.0
                && params.compression >= -1.0 && params.compression <= 1.0
                && params.blend >= 0.0 && params.blend <= 1.0;
            
            black_box((params, valid));
        })
    });
    
    c.bench_function("image_params_validation", |b| {
        b.iter(|| {
            let params = ImageUpscaleParams {
                scale_factor: 2.0,
                model: UpscaleModel::Iris3,
                compression: 0.0,
                blend: 0.1,
                output_format: ImageFormat::Png,
            };
            
            // Simulate validation
            let valid = params.scale_factor > 0.0 && params.scale_factor <= 4.0
                && params.compression >= -1.0 && params.compression <= 1.0
                && params.blend >= 0.0 && params.blend <= 1.0;
            
            black_box((params, valid));
        })
    });
}

/// Benchmark error handling
fn benchmark_error_handling(c: &mut Criterion) {
    c.bench_function("error_message_generation", |b| {
        b.iter(|| {
            let errors = vec![
                TvaiError::TopazNotFound("/test/path".to_string()),
                TvaiError::FfmpegError("Test error".to_string()),
                TvaiError::InvalidParameter("Test param".to_string()),
                TvaiError::GpuError("Test GPU error".to_string()),
            ];
            
            for error in errors {
                let friendly_msg = error.user_friendly_message();
                let category = error.category();
                let recoverable = error.is_recoverable();
                
                black_box((friendly_msg, category, recoverable));
            }
        })
    });
}

/// Benchmark model string operations
fn benchmark_model_operations(c: &mut Criterion) {
    c.bench_function("model_string_conversion", |b| {
        b.iter(|| {
            let models = vec![
                UpscaleModel::Iris3,
                UpscaleModel::Nyx3,
                UpscaleModel::Thf4,
                UpscaleModel::Ghq5,
            ];
            
            for model in models {
                let model_str = model.as_str();
                let description = model.description();
                let forced_scale = model.forces_scale();
                
                black_box((model_str, description, forced_scale));
            }
        })
    });
    
    c.bench_function("interpolation_model_operations", |b| {
        b.iter(|| {
            let models = vec![
                InterpolationModel::Apo8,
                InterpolationModel::Chr2,
                InterpolationModel::Apf1,
                InterpolationModel::Chf3,
            ];
            
            for model in models {
                let model_str = model.as_str();
                let description = model.description();
                
                black_box((model_str, description));
            }
        })
    });
}

/// Benchmark system detection
fn benchmark_system_detection(c: &mut Criterion) {
    c.bench_function("topaz_detection", |b| {
        b.iter(|| {
            let topaz_path = detect_topaz_installation();
            black_box(topaz_path);
        })
    });
    
    c.bench_function("ffmpeg_detection", |b| {
        b.iter(|| {
            let ffmpeg_info = detect_ffmpeg();
            black_box(ffmpeg_info);
        })
    });
    
    c.bench_function("gpu_support_detection", |b| {
        b.iter(|| {
            let gpu_info = detect_gpu_support();
            black_box(gpu_info);
        })
    });
}

criterion_group!(
    benches,
    benchmark_gpu_detection,
    benchmark_settings_management,
    benchmark_preset_management,
    benchmark_temp_file_management,
    benchmark_performance_monitoring,
    benchmark_parameter_validation,
    benchmark_error_handling,
    benchmark_model_operations,
    benchmark_system_detection
);

criterion_main!(benches);
