//! Report generation for EDD experiments.
//!
//! This module provides functionality to generate various report formats
//! from experiment results:
//! - Markdown reports
//! - JSON reports
//! - HTML reports (planned)
//!
//! # Report Contents
//!
//! Generated reports include:
//! - Experiment metadata
//! - Verification test results
//! - Falsification criteria results
//! - Reproducibility verification
//! - Execution metrics
//!
//! # Example
//!
//! ```ignore
//! let result = runner.run("experiment.yaml")?;
//! let report = ReportGenerator::markdown(&result)?;
//! std::fs::write("report.md", report)?;
//! ```

use super::runner::{
    EmcComplianceReport, ExecutionMetrics, ExperimentResult, FalsificationSummary,
    ReproducibilitySummary, VerificationSummary,
};
use std::fmt::Write;

/// Report format options.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReportFormat {
    /// Markdown format
    Markdown,
    /// JSON format
    Json,
    /// Plain text format
    Text,
}

/// Report generator for experiment results.
pub struct ReportGenerator;

impl ReportGenerator {
    /// Generate a markdown report from experiment results.
    ///
    /// # Errors
    /// Returns error if formatting fails.
    pub fn markdown(result: &ExperimentResult) -> Result<String, String> {
        let mut report = String::new();

        // Header
        writeln!(report, "# Experiment Report: {}", result.name).map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        // Metadata
        writeln!(report, "## Metadata").map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;
        writeln!(report, "| Field | Value |").map_err(|e| e.to_string())?;
        writeln!(report, "|-------|-------|").map_err(|e| e.to_string())?;
        writeln!(report, "| Experiment ID | {} |", result.experiment_id)
            .map_err(|e| e.to_string())?;
        writeln!(report, "| Seed | {} |", result.seed).map_err(|e| e.to_string())?;
        writeln!(
            report,
            "| Status | {} |",
            if result.passed { "PASSED" } else { "FAILED" }
        )
        .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        // Verification Tests
        writeln!(report, "## Verification Tests").map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;
        Self::write_verification_summary(&mut report, &result.verification)?;

        // Falsification Criteria
        writeln!(report, "## Falsification Criteria").map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;
        Self::write_falsification_summary(&mut report, &result.falsification)?;

        // Reproducibility
        if let Some(ref repro) = result.reproducibility {
            writeln!(report, "## Reproducibility").map_err(|e| e.to_string())?;
            writeln!(report).map_err(|e| e.to_string())?;
            Self::write_reproducibility_summary(&mut report, repro)?;
        }

        // Execution Metrics
        writeln!(report, "## Execution Metrics").map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;
        Self::write_execution_metrics(&mut report, &result.execution)?;

        // Warnings
        if !result.warnings.is_empty() {
            writeln!(report, "## Warnings").map_err(|e| e.to_string())?;
            writeln!(report).map_err(|e| e.to_string())?;
            for warning in &result.warnings {
                writeln!(report, "- {warning}").map_err(|e| e.to_string())?;
            }
            writeln!(report).map_err(|e| e.to_string())?;
        }

        // Footer
        writeln!(report, "---").map_err(|e| e.to_string())?;
        writeln!(
            report,
            "*Generated by simular v{}*",
            env!("CARGO_PKG_VERSION")
        )
        .map_err(|e| e.to_string())?;

        Ok(report)
    }

    fn write_verification_summary(
        report: &mut String,
        summary: &VerificationSummary,
    ) -> Result<(), String> {
        writeln!(
            report,
            "**Summary:** {} passed, {} failed out of {} total",
            summary.passed, summary.failed, summary.total
        )
        .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        if !summary.tests.is_empty() {
            writeln!(
                report,
                "| ID | Name | Status | Expected | Actual | Tolerance |"
            )
            .map_err(|e| e.to_string())?;
            writeln!(report, "|---|---|---|---|---|---|").map_err(|e| e.to_string())?;

            for test in &summary.tests {
                let status = if test.passed { "PASS" } else { "FAIL" };
                let expected = test
                    .expected
                    .map_or_else(|| "-".to_string(), |v| format!("{v:.6}"));
                let actual = test
                    .actual
                    .map_or_else(|| "-".to_string(), |v| format!("{v:.6}"));
                let tolerance = test
                    .tolerance
                    .map_or_else(|| "-".to_string(), |v| format!("{v:.2e}"));

                writeln!(
                    report,
                    "| {} | {} | {} | {} | {} | {} |",
                    test.id, test.name, status, expected, actual, tolerance
                )
                .map_err(|e| e.to_string())?;
            }
            writeln!(report).map_err(|e| e.to_string())?;
        }

        Ok(())
    }

    fn write_falsification_summary(
        report: &mut String,
        summary: &FalsificationSummary,
    ) -> Result<(), String> {
        writeln!(
            report,
            "**Summary:** {} passed, {} triggered out of {} total",
            summary.passed, summary.triggered, summary.total
        )
        .map_err(|e| e.to_string())?;

        if summary.jidoka_triggered {
            writeln!(report, "\n**Jidoka:** TRIGGERED (stop-on-error)")
                .map_err(|e| e.to_string())?;
        }
        writeln!(report).map_err(|e| e.to_string())?;

        if !summary.criteria.is_empty() {
            writeln!(report, "| ID | Name | Triggered | Severity | Condition |")
                .map_err(|e| e.to_string())?;
            writeln!(report, "|---|---|---|---|---|").map_err(|e| e.to_string())?;

            for crit in &summary.criteria {
                let triggered = if crit.triggered { "YES" } else { "NO" };
                writeln!(
                    report,
                    "| {} | {} | {} | {} | {} |",
                    crit.id, crit.name, triggered, crit.severity, crit.condition
                )
                .map_err(|e| e.to_string())?;
            }
            writeln!(report).map_err(|e| e.to_string())?;
        }

        Ok(())
    }

    fn write_reproducibility_summary(
        report: &mut String,
        summary: &ReproducibilitySummary,
    ) -> Result<(), String> {
        writeln!(report, "| Property | Value |").map_err(|e| e.to_string())?;
        writeln!(report, "|---|---|").map_err(|e| e.to_string())?;
        writeln!(
            report,
            "| Passed | {} |",
            if summary.passed { "YES" } else { "NO" }
        )
        .map_err(|e| e.to_string())?;
        writeln!(report, "| Runs | {} |", summary.runs).map_err(|e| e.to_string())?;
        writeln!(report, "| Identical | {} |", summary.identical).map_err(|e| e.to_string())?;
        writeln!(report, "| Platform | {} |", summary.platform).map_err(|e| e.to_string())?;
        writeln!(report, "| Reference Hash | `{}` |", summary.reference_hash)
            .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        Ok(())
    }

    fn write_execution_metrics(
        report: &mut String,
        metrics: &ExecutionMetrics,
    ) -> Result<(), String> {
        writeln!(report, "| Metric | Value |").map_err(|e| e.to_string())?;
        writeln!(report, "|---|---|").map_err(|e| e.to_string())?;
        writeln!(report, "| Duration | {} ms |", metrics.duration_ms).map_err(|e| e.to_string())?;
        writeln!(report, "| Steps | {} |", metrics.steps).map_err(|e| e.to_string())?;
        writeln!(report, "| Replications | {} |", metrics.replications)
            .map_err(|e| e.to_string())?;

        if let Some(mem) = metrics.peak_memory_bytes {
            writeln!(report, "| Peak Memory | {mem} bytes |").map_err(|e| e.to_string())?;
        }
        writeln!(report).map_err(|e| e.to_string())?;

        Ok(())
    }

    /// Generate a JSON report from experiment results.
    ///
    /// # Errors
    /// Returns error if serialization fails.
    pub fn json(result: &ExperimentResult) -> Result<String, String> {
        serde_json::to_string_pretty(result)
            .map_err(|e| format!("Failed to serialize to JSON: {e}"))
    }

    /// Generate a plain text report from experiment results.
    ///
    /// # Errors
    /// Returns error if formatting fails.
    pub fn text(result: &ExperimentResult) -> Result<String, String> {
        let mut report = String::new();

        let status = if result.passed { "PASSED" } else { "FAILED" };
        writeln!(report, "EXPERIMENT REPORT: {}", result.name).map_err(|e| e.to_string())?;
        writeln!(
            report,
            "================================================================================"
        )
        .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;
        writeln!(report, "ID:     {}", result.experiment_id).map_err(|e| e.to_string())?;
        writeln!(report, "Seed:   {}", result.seed).map_err(|e| e.to_string())?;
        writeln!(report, "Status: {status}").map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        writeln!(report, "VERIFICATION TESTS").map_err(|e| e.to_string())?;
        writeln!(
            report,
            "--------------------------------------------------------------------------------"
        )
        .map_err(|e| e.to_string())?;
        writeln!(report, "Total:  {}", result.verification.total).map_err(|e| e.to_string())?;
        writeln!(report, "Passed: {}", result.verification.passed).map_err(|e| e.to_string())?;
        writeln!(report, "Failed: {}", result.verification.failed).map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        writeln!(report, "FALSIFICATION CRITERIA").map_err(|e| e.to_string())?;
        writeln!(
            report,
            "--------------------------------------------------------------------------------"
        )
        .map_err(|e| e.to_string())?;
        writeln!(report, "Total:     {}", result.falsification.total).map_err(|e| e.to_string())?;
        writeln!(report, "Passed:    {}", result.falsification.passed)
            .map_err(|e| e.to_string())?;
        writeln!(report, "Triggered: {}", result.falsification.triggered)
            .map_err(|e| e.to_string())?;
        writeln!(
            report,
            "Jidoka:    {}",
            if result.falsification.jidoka_triggered {
                "TRIGGERED"
            } else {
                "OK"
            }
        )
        .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        writeln!(report, "EXECUTION").map_err(|e| e.to_string())?;
        writeln!(
            report,
            "--------------------------------------------------------------------------------"
        )
        .map_err(|e| e.to_string())?;
        writeln!(report, "Duration:     {} ms", result.execution.duration_ms)
            .map_err(|e| e.to_string())?;
        writeln!(report, "Replications: {}", result.execution.replications)
            .map_err(|e| e.to_string())?;
        writeln!(report).map_err(|e| e.to_string())?;

        writeln!(
            report,
            "================================================================================"
        )
        .map_err(|e| e.to_string())?;
        writeln!(report, "RESULT: {status}").map_err(|e| e.to_string())?;

        Ok(report)
    }

    /// Generate a markdown report for EMC compliance.
    ///
    /// # Errors
    /// Returns error if formatting fails.
    pub fn emc_compliance_markdown(report: &EmcComplianceReport) -> Result<String, String> {
        let mut output = String::new();

        writeln!(
            output,
            "# EMC Compliance Report: {}",
            report.experiment_name
        )
        .map_err(|e| e.to_string())?;
        writeln!(output).map_err(|e| e.to_string())?;

        let status = if report.passed {
            "COMPLIANT"
        } else {
            "NON-COMPLIANT"
        };
        writeln!(output, "**Status:** {status}").map_err(|e| e.to_string())?;
        writeln!(output).map_err(|e| e.to_string())?;

        // EDD Compliance Checklist
        writeln!(output, "## EDD Compliance Checklist").map_err(|e| e.to_string())?;
        writeln!(output).map_err(|e| e.to_string())?;
        writeln!(output, "| Requirement | Status |").map_err(|e| e.to_string())?;
        writeln!(output, "|---|---|").map_err(|e| e.to_string())?;

        let check = |b: bool| if b { "PASS" } else { "FAIL" };
        writeln!(
            output,
            "| EDD-01: EMC Reference | {} |",
            check(report.edd_compliance.edd_01_emc_reference)
        )
        .map_err(|e| e.to_string())?;
        writeln!(
            output,
            "| EDD-02: Verification Tests | {} |",
            check(report.edd_compliance.edd_02_verification_tests)
        )
        .map_err(|e| e.to_string())?;
        writeln!(
            output,
            "| EDD-03: Seed Specified | {} |",
            check(report.edd_compliance.edd_03_seed_specified)
        )
        .map_err(|e| e.to_string())?;
        writeln!(
            output,
            "| EDD-04: Falsification Criteria | {} |",
            check(report.edd_compliance.edd_04_falsification_criteria)
        )
        .map_err(|e| e.to_string())?;
        writeln!(
            output,
            "| EDD-05: Hypothesis (Optional) | {} |",
            check(report.edd_compliance.edd_05_hypothesis)
        )
        .map_err(|e| e.to_string())?;
        writeln!(output).map_err(|e| e.to_string())?;

        // Errors
        if !report.schema_errors.is_empty() || !report.emc_errors.is_empty() {
            writeln!(output, "## Errors").map_err(|e| e.to_string())?;
            writeln!(output).map_err(|e| e.to_string())?;

            for err in &report.schema_errors {
                writeln!(output, "- Schema: {err}").map_err(|e| e.to_string())?;
            }
            for err in &report.emc_errors {
                writeln!(output, "- EMC: {err}").map_err(|e| e.to_string())?;
            }
            writeln!(output).map_err(|e| e.to_string())?;
        }

        // Warnings
        if !report.warnings.is_empty() {
            writeln!(output, "## Warnings").map_err(|e| e.to_string())?;
            writeln!(output).map_err(|e| e.to_string())?;
            for warning in &report.warnings {
                writeln!(output, "- {warning}").map_err(|e| e.to_string())?;
            }
            writeln!(output).map_err(|e| e.to_string())?;
        }

        // Footer
        writeln!(output, "---").map_err(|e| e.to_string())?;
        writeln!(
            output,
            "*Generated by simular v{}*",
            env!("CARGO_PKG_VERSION")
        )
        .map_err(|e| e.to_string())?;

        Ok(output)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::edd::runner::{
        EddComplianceChecklist, FalsificationCriterionResult, VerificationTestSummary,
    };

    fn sample_result() -> ExperimentResult {
        ExperimentResult {
            name: "Test Experiment".to_string(),
            experiment_id: "EXP-001".to_string(),
            seed: 42,
            passed: true,
            verification: VerificationSummary {
                total: 2,
                passed: 2,
                failed: 0,
                tests: vec![VerificationTestSummary {
                    id: "VT-001".to_string(),
                    name: "Basic test".to_string(),
                    passed: true,
                    expected: Some(10.0),
                    actual: Some(10.0),
                    tolerance: Some(0.001),
                    error: None,
                }],
            },
            falsification: FalsificationSummary {
                total: 1,
                passed: 1,
                triggered: 0,
                jidoka_triggered: false,
                criteria: vec![FalsificationCriterionResult {
                    id: "FC-001".to_string(),
                    name: "Error bound".to_string(),
                    triggered: false,
                    condition: "error < 0.01".to_string(),
                    severity: "critical".to_string(),
                    value: None,
                    threshold: Some(0.01),
                }],
            },
            reproducibility: Some(ReproducibilitySummary {
                passed: true,
                runs: 3,
                identical: true,
                reference_hash: "abc123".to_string(),
                run_hashes: vec!["abc123".to_string(); 3],
                platform: "x86_64".to_string(),
            }),
            execution: ExecutionMetrics {
                duration_ms: 100,
                steps: 1000,
                replications: 30,
                peak_memory_bytes: Some(1024 * 1024),
            },
            artifacts: Vec::new(),
            warnings: vec!["Test warning".to_string()],
        }
    }

    #[test]
    fn test_markdown_report() {
        let result = sample_result();
        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.expect("markdown generation should succeed");
        assert!(report.contains("# Experiment Report: Test Experiment"));
        assert!(report.contains("PASSED"));
        assert!(report.contains("42"));
        assert!(report.contains("VT-001"));
    }

    #[test]
    fn test_json_report() {
        let result = sample_result();
        let report = ReportGenerator::json(&result);
        assert!(report.is_ok());
        let report = report.expect("json generation should succeed");
        assert!(report.contains("\"name\": \"Test Experiment\""));
        assert!(report.contains("\"seed\": 42"));
    }

    #[test]
    fn test_text_report() {
        let result = sample_result();
        let report = ReportGenerator::text(&result);
        assert!(report.is_ok());
        let report = report.expect("text generation should succeed");
        assert!(report.contains("EXPERIMENT REPORT: Test Experiment"));
        assert!(report.contains("RESULT: PASSED"));
    }

    #[test]
    fn test_emc_compliance_markdown() {
        let report = EmcComplianceReport {
            experiment_name: "Test".to_string(),
            passed: true,
            schema_errors: Vec::new(),
            emc_errors: Vec::new(),
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: true,
                edd_02_verification_tests: true,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: true,
                edd_05_hypothesis: true,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.expect("compliance markdown should succeed");
        assert!(output.contains("COMPLIANT"));
        assert!(output.contains("EDD-01"));
    }

    #[test]
    fn test_failed_report() {
        let mut result = sample_result();
        result.passed = false;
        result.verification.failed = 1;
        result.verification.passed = 1;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.expect("markdown for failed result should succeed");
        assert!(report.contains("FAILED"));
    }

    #[test]
    fn test_report_format_enum() {
        let markdown = ReportFormat::Markdown;
        let json = ReportFormat::Json;
        let text = ReportFormat::Text;

        assert_eq!(markdown, ReportFormat::Markdown);
        assert_ne!(json, ReportFormat::Markdown);
        assert_ne!(text, ReportFormat::Json);
    }

    #[test]
    fn test_markdown_report_no_reproducibility() {
        let mut result = sample_result();
        result.reproducibility = None;
        result.warnings.clear();

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        // Should not contain Reproducibility section
        assert!(!report.contains("## Reproducibility"));
        // Should not contain Warnings section
        assert!(!report.contains("## Warnings"));
    }

    #[test]
    fn test_markdown_report_with_memory() {
        let result = sample_result();
        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        // Should contain memory info
        assert!(report.contains("1048576")); // 1024*1024
    }

    #[test]
    fn test_text_report_with_jidoka() {
        let mut result = sample_result();
        result.falsification.jidoka_triggered = true;

        let report = ReportGenerator::text(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("TRIGGERED"));
    }

    #[test]
    fn test_markdown_verification_with_no_expected() {
        let mut result = sample_result();
        result.verification.tests = vec![VerificationTestSummary {
            id: "VT-002".to_string(),
            name: "No expected".to_string(),
            passed: true,
            expected: None,
            actual: None,
            tolerance: None,
            error: None,
        }];

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
    }

    #[test]
    fn test_markdown_falsification_with_triggered() {
        let mut result = sample_result();
        result.falsification.criteria[0].triggered = true;
        result.falsification.triggered = 1;
        result.falsification.passed = 0;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("YES"));
    }

    #[test]
    fn test_markdown_jidoka_triggered() {
        let mut result = sample_result();
        result.falsification.jidoka_triggered = true;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("Jidoka"));
        assert!(report.contains("TRIGGERED"));
    }

    #[test]
    fn test_emc_compliance_with_errors() {
        let report = EmcComplianceReport {
            experiment_name: "Error Test".to_string(),
            passed: false,
            schema_errors: vec!["Schema error 1".to_string()],
            emc_errors: vec!["EMC error 1".to_string()],
            warnings: vec!["Warning 1".to_string()],
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: false,
                edd_02_verification_tests: false,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: false,
                edd_05_hypothesis: false,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();
        assert!(output.contains("NON-COMPLIANT"));
        assert!(output.contains("Schema: Schema error 1"));
        assert!(output.contains("EMC: EMC error 1"));
        assert!(output.contains("Warning 1"));
        assert!(output.contains("FAIL"));
    }

    #[test]
    fn test_markdown_execution_no_memory() {
        let mut result = sample_result();
        result.execution.peak_memory_bytes = None;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        // Should not contain Peak Memory line since it's None
        assert!(!report.contains("Peak Memory"));
    }

    #[test]
    fn test_verification_empty_tests() {
        let mut result = sample_result();
        result.verification.tests.clear();
        result.verification.total = 0;
        result.verification.passed = 0;
        result.verification.failed = 0;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("0 passed, 0 failed out of 0 total"));
    }

    #[test]
    fn test_falsification_empty_criteria() {
        let mut result = sample_result();
        result.falsification.criteria.clear();
        result.falsification.total = 0;
        result.falsification.passed = 0;
        result.falsification.triggered = 0;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("0 passed, 0 triggered out of 0 total"));
    }

    #[test]
    fn test_compliance_no_errors_no_warnings() {
        let report = EmcComplianceReport {
            experiment_name: "Clean".to_string(),
            passed: true,
            schema_errors: Vec::new(),
            emc_errors: Vec::new(),
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: true,
                edd_02_verification_tests: true,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: true,
                edd_05_hypothesis: true,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();
        assert!(output.contains("COMPLIANT"));
        // Should not contain Errors or Warnings sections
        assert!(!output.contains("## Errors"));
        assert!(!output.contains("## Warnings"));
    }

    #[test]
    fn test_report_format_debug() {
        let format = ReportFormat::Markdown;
        let debug_str = format!("{format:?}");
        assert!(debug_str.contains("Markdown"));
    }

    #[test]
    fn test_report_format_clone() {
        let format = ReportFormat::Json;
        let cloned = format;
        assert_eq!(cloned, ReportFormat::Json);
    }

    #[test]
    fn test_report_format_copy() {
        let format = ReportFormat::Text;
        let copied = format;
        assert_eq!(format, copied);
    }

    #[test]
    fn test_text_report_without_jidoka() {
        let result = sample_result();
        let report = ReportGenerator::text(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("Jidoka:    OK"));
    }

    #[test]
    fn test_markdown_report_content_details() {
        let result = sample_result();
        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();

        // Check metadata table
        assert!(report.contains("| Field | Value |"));
        assert!(report.contains("| Experiment ID |"));
        assert!(report.contains("| Seed |"));
        assert!(report.contains("| Status |"));

        // Check verification section
        assert!(report.contains("## Verification Tests"));
        assert!(report.contains("**Summary:**"));

        // Check falsification section
        assert!(report.contains("## Falsification Criteria"));

        // Check reproducibility section (sample_result has it)
        assert!(report.contains("## Reproducibility"));

        // Check execution section
        assert!(report.contains("## Execution Metrics"));
        assert!(report.contains("| Duration |"));
        assert!(report.contains("| Steps |"));
        assert!(report.contains("| Replications |"));
    }

    #[test]
    fn test_json_report_deserialization() {
        let result = sample_result();
        let json = ReportGenerator::json(&result);
        assert!(json.is_ok());
        let json = json.ok().unwrap();

        // Should be valid JSON
        let parsed: Result<serde_json::Value, _> = serde_json::from_str(&json);
        assert!(parsed.is_ok());
    }

    #[test]
    fn test_text_report_full_content() {
        let result = sample_result();
        let report = ReportGenerator::text(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();

        assert!(report.contains("EXPERIMENT REPORT:"));
        assert!(report.contains("ID:"));
        assert!(report.contains("Seed:"));
        assert!(report.contains("VERIFICATION TESTS"));
        assert!(report.contains("FALSIFICATION CRITERIA"));
        assert!(report.contains("EXECUTION"));
        assert!(report.contains("Duration:"));
        assert!(report.contains("Replications:"));
    }

    #[test]
    fn test_emc_compliance_only_schema_errors() {
        let report = EmcComplianceReport {
            experiment_name: "Schema Error".to_string(),
            passed: false,
            schema_errors: vec!["Schema error only".to_string()],
            emc_errors: Vec::new(),
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: true,
                edd_02_verification_tests: true,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: true,
                edd_05_hypothesis: true,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();
        assert!(output.contains("Schema: Schema error only"));
    }

    #[test]
    fn test_emc_compliance_only_emc_errors() {
        let report = EmcComplianceReport {
            experiment_name: "EMC Error".to_string(),
            passed: false,
            schema_errors: Vec::new(),
            emc_errors: vec!["EMC error only".to_string()],
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: true,
                edd_02_verification_tests: true,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: true,
                edd_05_hypothesis: true,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();
        assert!(output.contains("EMC: EMC error only"));
    }

    #[test]
    fn test_verification_with_error_field() {
        let mut result = sample_result();
        result.verification.tests = vec![VerificationTestSummary {
            id: "VT-ERR".to_string(),
            name: "Test with error".to_string(),
            passed: false,
            expected: Some(10.0),
            actual: Some(15.0),
            tolerance: Some(0.001),
            error: Some("Out of tolerance".to_string()),
        }];
        result.verification.passed = 0;
        result.verification.failed = 1;

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("VT-ERR"));
        assert!(report.contains("FAIL"));
    }

    #[test]
    fn test_reproducibility_not_passed() {
        let mut result = sample_result();
        result.reproducibility = Some(ReproducibilitySummary {
            passed: false,
            runs: 3,
            identical: false,
            reference_hash: "abc123".to_string(),
            run_hashes: vec![
                "abc123".to_string(),
                "def456".to_string(),
                "ghi789".to_string(),
            ],
            platform: "x86_64".to_string(),
        });

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("| Passed | NO |"));
        assert!(report.contains("| Identical | false |"));
    }

    #[test]
    fn test_multiple_verification_tests() {
        let mut result = sample_result();
        result.verification.tests = vec![
            VerificationTestSummary {
                id: "VT-001".to_string(),
                name: "Test 1".to_string(),
                passed: true,
                expected: Some(1.0),
                actual: Some(1.0),
                tolerance: Some(0.01),
                error: None,
            },
            VerificationTestSummary {
                id: "VT-002".to_string(),
                name: "Test 2".to_string(),
                passed: true,
                expected: Some(2.0),
                actual: Some(2.0),
                tolerance: Some(0.01),
                error: None,
            },
            VerificationTestSummary {
                id: "VT-003".to_string(),
                name: "Test 3".to_string(),
                passed: false,
                expected: Some(3.0),
                actual: Some(3.5),
                tolerance: Some(0.01),
                error: Some("Test 3 failed".to_string()),
            },
        ];

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("VT-001"));
        assert!(report.contains("VT-002"));
        assert!(report.contains("VT-003"));
    }

    #[test]
    fn test_multiple_falsification_criteria() {
        let mut result = sample_result();
        result.falsification.criteria = vec![
            FalsificationCriterionResult {
                id: "FC-001".to_string(),
                name: "Criterion 1".to_string(),
                triggered: false,
                condition: "x < 1".to_string(),
                severity: "warning".to_string(),
                value: Some(0.5),
                threshold: Some(1.0),
            },
            FalsificationCriterionResult {
                id: "FC-002".to_string(),
                name: "Criterion 2".to_string(),
                triggered: true,
                condition: "y > 10".to_string(),
                severity: "critical".to_string(),
                value: Some(15.0),
                threshold: Some(10.0),
            },
        ];

        let report = ReportGenerator::markdown(&result);
        assert!(report.is_ok());
        let report = report.ok().unwrap();
        assert!(report.contains("FC-001"));
        assert!(report.contains("FC-002"));
    }

    #[test]
    fn test_all_edd_compliance_fail() {
        let report = EmcComplianceReport {
            experiment_name: "All Fail".to_string(),
            passed: false,
            schema_errors: Vec::new(),
            emc_errors: Vec::new(),
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: false,
                edd_02_verification_tests: false,
                edd_03_seed_specified: false,
                edd_04_falsification_criteria: false,
                edd_05_hypothesis: false,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();

        // Should contain FAIL for all checklist items
        let fail_count = output.matches("| FAIL |").count();
        assert_eq!(fail_count, 5, "All 5 EDD checks should fail");
    }

    #[test]
    fn test_emc_compliance_footer() {
        let report = EmcComplianceReport {
            experiment_name: "Footer Test".to_string(),
            passed: true,
            schema_errors: Vec::new(),
            emc_errors: Vec::new(),
            warnings: Vec::new(),
            edd_compliance: EddComplianceChecklist {
                edd_01_emc_reference: true,
                edd_02_verification_tests: true,
                edd_03_seed_specified: true,
                edd_04_falsification_criteria: true,
                edd_05_hypothesis: true,
            },
        };

        let output = ReportGenerator::emc_compliance_markdown(&report);
        assert!(output.is_ok());
        let output = output.ok().unwrap();
        assert!(output.contains("---"));
        assert!(output.contains("*Generated by simular v"));
    }
}
