pub fn move_file(
    target: &std::path::Path,
    destination: &std::path::Path,
    create_dirs: bool,
) -> std::io::Result<()> {
    // check if the target file exists
    if !target.exists() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("Source file not found: {:?}", target),
        ));
    }

    // determine the final destination path
    let final_destination = if destination.is_dir() {
        // if the destination is a directory, then append the target file name to the destination path
        let mut dest_path = destination.to_path_buf();
        if let Some(file_name) = target.file_name() {
            dest_path.push(file_name);
        }
        dest_path
    } else {
        // if destination is already a file path, then use it directly
        destination.to_path_buf()
    };

    // create the necessary directories if the flag is set
    if create_dirs {
        if let Some(parent) = final_destination.parent() {
            std::fs::create_dir_all(parent)?;
        }
    }

    // attempt to rename (move) the file
    match std::fs::rename(target, &final_destination) {
        Ok(_) => Ok(()),
        Err(e) => {
            eprintln!("Failed to rename file: {:?}. Trying fallback method...", e);
            // if rename fails, try to copy the file instead
            if let Err(copy_error) = std::fs::copy(target, &final_destination) {
                return Err(std::io::Error::new(
                    std::io::ErrorKind::Other,
                    format!("Failed to copy file: {:?}", copy_error),
                ));
            }
            if let Err(remove_error) = std::fs::remove_file(target) {
                return Err(std::io::Error::new(
                    std::io::ErrorKind::Other,
                    format!("Failed to remove original file: {:?}", remove_error),
                ));
            }
            Ok(())
        }
    }
}

pub fn copy_file(
    target: &std::path::Path,
    destination: &std::path::Path,
    create_dirs: bool,
) -> std::io::Result<()> {
    // check if the target file exists
    if !target.exists() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("Source file not found: {:?}", target),
        ));
    }

    // determine the final destination path
    let final_destination = if destination.is_dir() {
        // if the destination is a directory, append the target file name
        let mut dest_path = destination.to_path_buf();
        if let Some(file_name) = target.file_name() {
            dest_path.push(file_name);
        }
        dest_path
    } else {
        // if destination is a file path, use it directly
        destination.to_path_buf()
    };

    // create the necessary directories if the flag is set
    if create_dirs {
        if let Some(parent) = final_destination.parent() {
            std::fs::create_dir_all(parent)?;
        }
    }

    // copy the file
    // why need to use map???
    std::fs::copy(target, &final_destination).map(|_| ())
}

pub fn delete_file(file_path: &std::path::Path) -> std::io::Result<()> {
    // attempt to delete the file
    if file_path.exists() {
        std::fs::remove_file(file_path)?;
        Ok(())
    } else {
        Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("File not found: {:?}", file_path),
        ))
    }
}

pub fn create_directory(directory_path: &std::path::Path) -> std::io::Result<()> {
    // attempt to create the directory
    std::fs::create_dir_all(directory_path)
}
