//! Snapshot testing for dupe-core output formats
//!
//! Uses the `insta` crate to capture and compare output snapshots.
//! If output format changes, tests will fail until snapshots are reviewed and updated.

#[cfg(test)]
mod tests {
    use crate::{DuplicateMatch, Scanner};
    use insta::{assert_debug_snapshot, assert_json_snapshot};
    use std::path::PathBuf;

    #[test]
    fn snapshot_duplicate_match_json() {
        let dup = DuplicateMatch {
            file1: "src/main.rs".to_string(),
            file2: "src/lib.rs".to_string(),
            start_line1: 10,
            start_line2: 25,
            length: 50,
            similarity: 0.95,
            hash: 0x123456789ABCDEF,
        };

        assert_json_snapshot!(dup, @r###"
        {
          "file1": "src/main.rs",
          "file2": "src/lib.rs",
          "start_line1": 10,
          "start_line2": 25,
          "length": 50,
          "similarity": 0.95,
          "hash": 81985529216486895
        }
        "###);
    }

    #[test]
    fn snapshot_empty_scan_result() {
        let scanner = Scanner::new().unwrap();
        let paths = vec![PathBuf::from("nonexistent")];

        let result = scanner.scan(paths);

        // Should succeed with 0 files scanned
        assert!(result.is_ok());
        let mut report = result.unwrap();

        // Duration can vary (0-10ms), normalize for snapshot
        report.stats.duration_ms = 0;

        assert_debug_snapshot!(report, @r"
        Report {
            files_scanned: 0,
            functions_analyzed: 0,
            duplicates: [],
            stats: ScanStats {
                total_lines: 0,
                total_tokens: 0,
                unique_hashes: 0,
                duration_ms: 0,
            },
        }
        ");
    }

    #[test]
    fn snapshot_test_duplicates_report() {
        use std::path::Path;

        // Only run if test_duplicates exists
        if !Path::new("test_duplicates").exists() {
            return;
        }

        let scanner = Scanner::with_config(3, 0.70).unwrap();
        let paths = vec![PathBuf::from("test_duplicates")];

        let result = scanner.scan(paths);
        assert!(result.is_ok());

        let report = result.unwrap();

        // Snapshot the structure (not exact values which may vary)
        assert!(report.files_scanned >= 1, "Should scan at least 1 file");
        assert!(
            report.functions_analyzed >= 1,
            "Should analyze at least 1 function"
        );

        // Snapshot a sample duplicate if found
        if let Some(dup) = report.duplicates.first() {
            assert_json_snapshot!("sample_duplicate", dup, {
                ".hash" => "[hash]",  // Hash values are dynamic
            });
        }
    }

    #[test]
    fn snapshot_scanner_configuration() {
        let scanner = Scanner::with_config(100, 0.95);

        // Scanner doesn't implement Debug, so just verify it was created
        assert!(scanner.is_ok());
    }

    #[test]
    fn snapshot_multiple_duplicates() {
        let duplicates = vec![
            DuplicateMatch {
                file1: "a.rs".to_string(),
                file2: "b.rs".to_string(),
                start_line1: 1,
                start_line2: 1,
                length: 10,
                similarity: 1.0,
                hash: 0xAAA,
            },
            DuplicateMatch {
                file1: "a.rs".to_string(),
                file2: "c.rs".to_string(),
                start_line1: 5,
                start_line2: 10,
                length: 15,
                similarity: 0.92,
                hash: 0xBBB,
            },
        ];

        assert_json_snapshot!(duplicates, {
            "[].hash" => "[hash]",  // Redact dynamic hashes
        });
    }
}
