#![cfg(feature = "bench")]

use pdfmake_rust::benchmark_report::{BenchmarkBaseline, BenchmarkEntry, ThresholdRule, compare_result};
use serde::Deserialize;
use std::collections::BTreeMap;

#[derive(Debug, Deserialize)]
struct ThresholdsFile {
    default: ThresholdRule,
    benchmarks: BTreeMap<String, ThresholdRule>,
}

#[test]
fn compare_result_passes_small_relative_change() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 103.0, pdf_size_kb: 143.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.status, "通过");
}

#[test]
fn compare_result_warns_in_mid_band() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 107.0, pdf_size_kb: 144.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.status, "警告");
}

#[test]
fn compare_result_fails_large_regression() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 120.0, pdf_size_kb: 145.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.status, "失败");
}

#[test]
fn compare_result_passes_below_min_absolute() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 0.5, pdf_size_kb: 10.0 };
    let current = BenchmarkEntry { time_ms: 0.6, pdf_size_kb: 10.0 };
    let result = compare_result("small", &baseline, &current, &rule);
    assert_eq!(result.status, "通过");
}

#[test]
fn compare_result_returns_correct_fields() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 103.0, pdf_size_kb: 143.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.name, "text_10k");
    assert_eq!(result.baseline_ms, 100.0);
    assert_eq!(result.current_ms, 103.0);
    assert!((result.change_pct - 3.0).abs() < 0.001);
    assert_eq!(result.baseline_pdf_size_kb, 142.0);
    assert_eq!(result.current_pdf_size_kb, 143.0);
}

#[test]
fn baseline_json_deserializes() {
    let data = include_str!("../benchmarks/baseline.json");
    let baseline: BenchmarkBaseline = serde_json::from_str(data).expect("Failed to parse baseline.json");
    assert_eq!(baseline.version, 1);
    assert_eq!(baseline.benchmarks.len(), 3);
    assert!(baseline.benchmarks.contains_key("text_10k"));
    assert!(baseline.benchmarks.contains_key("table_1000"));
    assert!(baseline.benchmarks.contains_key("pages_100"));
}

#[test]
fn thresholds_json_deserializes() {
    let data = include_str!("../benchmarks/thresholds.json");
    let thresholds: ThresholdsFile = serde_json::from_str(data)
        .expect("Failed to parse thresholds.json");
    assert_eq!(thresholds.default.pass_pct, 5.0);
    assert!(thresholds.benchmarks.contains_key("text_10k"));
    assert!(thresholds.benchmarks.contains_key("table_1000"));
    assert!(thresholds.benchmarks.contains_key("pages_100"));
}

#[test]
fn compare_result_improvement_passes() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 90.0, pdf_size_kb: 140.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.status, "警告");
    assert!((result.change_pct - (-10.0)).abs() < 0.001);
}

#[test]
fn compare_result_exact_boundary_warn() {
    let rule = ThresholdRule { pass_pct: 5.0,  fail_pct: 10.0, min_absolute_ms: 1.0 };
    let baseline = BenchmarkEntry { time_ms: 100.0, pdf_size_kb: 142.0 };
    let current = BenchmarkEntry { time_ms: 110.0, pdf_size_kb: 144.0 };
    let result = compare_result("text_10k", &baseline, &current, &rule);
    assert_eq!(result.status, "警告");
}
