use tempfile::TempDir;
use std::fs::{self};
use std::path::PathBuf;
use l_tool::cli::ImageCommands;
use l_tool::commands::image::commands::{handle_image_command, ConvertArgs, CompressArgs, ImgFormat, PngLevel};

fn create_test_image_png(path: &PathBuf) {
    let img = image::RgbImage::from_fn(4, 4, |x, y| {
        image::Rgb([(x * 10) as u8, (y * 20) as u8, 128])
    });
    img.save(path).expect("save png");
}

#[tokio::test]
async fn test_image_convert_default_output() {
    let dir = TempDir::new().unwrap();
    let input_path = dir.path().join("sample.png");
    create_test_image_png(&input_path);

    let args = ConvertArgs {
        input: input_path.clone(),
        format: ImgFormat::Jpeg,
        out_name: None,
        out_dir: None,
    };

    handle_image_command(ImageCommands::Convert(args)).await.unwrap();

    let expected = dir.path().join("sample.jpg");
    assert!(expected.exists());
    let meta = fs::metadata(expected).unwrap();
    assert!(meta.len() > 0);
}

#[tokio::test]
async fn test_image_compress_defaults_and_exists_check() {
    let dir = TempDir::new().unwrap();
    let input_path = dir.path().join("pic.png");
    create_test_image_png(&input_path);

    let args = CompressArgs {
        input: input_path.clone(),
        format: None,
        out_name: None,
        out_dir: None,
        quality: 75,
        png_level: PngLevel::Default,
    };
    handle_image_command(ImageCommands::Compress(args)).await.unwrap();

    let expected = dir.path().join("pic.compress.png");
    assert!(expected.exists());

    let dup_args = CompressArgs {
        input: input_path.clone(),
        format: None,
        out_name: None,
        out_dir: None,
        quality: 75,
        png_level: PngLevel::Default,
    };
    let result = handle_image_command(ImageCommands::Compress(dup_args)).await;
    assert!(result.is_err());
}

#[tokio::test]
async fn test_image_convert_to_qoi_and_ico() {
    let dir = TempDir::new().unwrap();
    let input_path = dir.path().join("a.png");
    create_test_image_png(&input_path);

    let qoi_args = ConvertArgs { input: input_path.clone(), format: ImgFormat::Qoi, out_name: None, out_dir: None };
    handle_image_command(ImageCommands::Convert(qoi_args)).await.unwrap();
    assert!(dir.path().join("a.qoi").exists());

    let ico_args = ConvertArgs { input: input_path.clone(), format: ImgFormat::Ico, out_name: None, out_dir: None };
    handle_image_command(ImageCommands::Convert(ico_args)).await.unwrap();
    assert!(dir.path().join("a.ico").exists());
}

#[tokio::test]
async fn test_image_compress_to_dds_should_error() {
    let dir = TempDir::new().unwrap();
    let input_path = dir.path().join("b.png");
    create_test_image_png(&input_path);

    let args = CompressArgs {
        input: input_path,
        format: Some(ImgFormat::Dds),
        out_name: None,
        out_dir: None,
        quality: 80,
        png_level: PngLevel::Default,
    };
    let result = handle_image_command(ImageCommands::Compress(args)).await;
    assert!(result.is_err());
}
