// Helper Functions for Creating Test Archive Files

use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use tempfile::TempDir;
use zip::{ZipWriter, SimpleFileOptions};
use flate2::{GzEncoder, Compression};
use tar::Builder;

/// Create test ZIP file with 3 files
pub fn create_test_zip(temp_dir: &TempDir) -> PathBuf {
    let zip_path = temp_dir.path().join("test.zip");
    let file = File::create(&zip_path).unwrap();
    let mut zip = ZipWriter::new(file);
    let options = SimpleFileOptions::default();
    
    // Add file1.txt
    zip.start_file("file1.txt", options).unwrap();
    zip.write_all(b"content of file 1").unwrap();
    
    // Add file2.txt
    zip.start_file("file2.txt", options).unwrap();
    zip.write_all(b"content of file 2").unwrap();
    
    // Add subdir/file3.txt
    zip.start_file("subdir/file3.txt", options).unwrap();
    zip.write_all(b"content of file 3 in subdir").unwrap();
    
    zip.finish().unwrap();
    zip_path
}

/// Create test TAR file with 3 files
pub fn create_test_tar(temp_dir: &TempDir) -> PathBuf {
    let tar_path = temp_dir.path().join("test.tar");
    let file = File::create(&tar_path).unwrap();
    let mut builder = Builder::new(file);
    
    // Add file1.txt
    let mut file1_header = tar::Header::new_gnu();
    file1_header.set_path("file1.txt").unwrap();
    file1_header.set_size(14);
    file1_header.set_cksum();
    builder.append_data(&file1_header, b"content of file 1").unwrap();
    
    // Add file2.txt
    let mut file2_header = tar::Header::new_gnu();
    file2_header.set_path("file2.txt").unwrap();
    file2_header.set_size(14);
    file2_header.set_cksum();
    builder.append_data(&file2_header, b"content of file 2").unwrap();
    
    // Add subdir/file3.txt
    let mut file3_header = tar::Header::new_gnu();
    file3_header.set_path("subdir/file3.txt").unwrap();
    file3_header.set_size(24);
    file3_header.set_cksum();
    builder.append_data(&file3_header, b"content of file 3 in subdir").unwrap();
    
    builder.finish().unwrap();
    tar_path
}

/// Create test GZIP file
pub fn create_test_gzip(temp_dir: &TempDir) -> PathBuf {
    let gz_path = temp_dir.path().join("test.txt.gz");
    let file = File::create(&gz_path).unwrap();
    let mut encoder = GzEncoder::new(file, Compression::default());
    encoder.write_all(b"test gzip content for validation").unwrap();
    encoder.finish().unwrap();
    gz_path
}

/// Create test TAR.GZ file
pub fn create_test_tar_gz(temp_dir: &TempDir) -> PathBuf {
    // First create TAR
    let tar_path = temp_dir.path().join("test.tar");
    let tar_file = File::create(&tar_path).unwrap();
    let mut builder = Builder::new(tar_file);
    
    let mut header1 = tar::Header::new_gnu();
    header1.set_path("file1.txt").unwrap();
    header1.set_size(10);
    header1.set_cksum();
    builder.append_data(&header1, b"file1 data").unwrap();
    
    let mut header2 = tar::Header::new_gnu();
    header2.set_path("file2.txt").unwrap();
    header2.set_size(10);
    header2.set_cksum();
    builder.append_data(&header2, b"file2 data").unwrap();
    
    builder.finish().unwrap();
    
    // Then compress with GZIP
    let tar_gz_path = temp_dir.path().join("test.tar.gz");
    let gz_file = File::create(&tar_gz_path).unwrap();
    let mut encoder = GzEncoder::new(gz_file, Compression::default());
    
    let tar_content = std::fs::read(&tar_path).unwrap();
    encoder.write_all(&tar_content).unwrap();
    encoder.finish().unwrap();
    
    // Clean up intermediate TAR
    std::fs::remove_file(&tar_path).unwrap();
    
    tar_gz_path
}

/// Create Zip Bomb test file (42KB → 5GB ratio)
pub fn create_zip_bomb_test() -> Vec<u8> {
    // Minimal ZIP bomb: small compressed, huge decompressed ratio
    // For testing, we just create a high ratio file (not actual bomb)
    use zip::{ZipWriter, SimpleFileOptions, CompressionMethod};
    
    let mut buffer = Vec::new();
    let writer = std::io::Cursor::new(&mut buffer);
    let mut zip = ZipWriter::new(writer);
    
    let options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored);  // No compression
    
    // Create file with compression ratio > 1000
    zip.start_file("bomb.txt", options).unwrap();
    // Small compressed, large indicated size (simulated)
    zip.write_all(&[0u8; 100]).unwrap();  // 100 bytes
    
    zip.finish().unwrap();
    buffer
}

/// Create Zip Slip test file with malicious paths
pub fn create_zip_slip_test() -> Vec<u8> {
    use zip::{ZipWriter, SimpleFileOptions};
    
    let mut buffer = Vec::new();
    let writer = std::io::Cursor::new(&mut buffer);
    let mut zip = ZipWriter::new(writer);
    let options = SimpleFileOptions::default();
    
    // Try to extract to /etc/passwd (malicious)
    zip.start_file("../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../etc/passwd", options).unwrap();
    zip.write_all(b"malicious content").unwrap();
    
    zip.finish().unwrap();
    buffer
}