use crate::utils::{db_put_simple, tmpdir};
use leveldb::comparator::OrdComparator;
use leveldb::database::Database;
use leveldb::database::cache::Cache;
use leveldb::iterator::{EntryIterator, Iterable};
use leveldb::options::{Compression, Options, ReadOptions};

#[cfg(feature = "logger")]
use leveldb::extension::{LogHandler, Logger};
#[cfg(feature = "logger")]
use std::time::SystemTime;

#[test]
fn test_minimal_options_with_db_operations() {
    let mut opts = Options::new();

    // Only set create_if_missing to true
    opts.create_if_missing = true;

    let tmp = tmpdir("minimal_options_test");
    let database = &mut Database::open(tmp.path(), opts).unwrap();

    // Test basic operations with minimal options
    db_put_simple(database, b"key1", b"abc");
    db_put_simple(database, b"key2", b"def");

    // Test iteration
    let read_opts = ReadOptions::new();
    let mut iter: EntryIterator<'_> = database.iter(read_opts);

    let (key1, val1) = iter.next().unwrap();
    assert_eq!(key1.as_bytes(), b"key1");
    assert_eq!(val1.as_bytes(), b"abc");
    let (key2, val2) = iter.next().unwrap();
    assert_eq!(key2.as_bytes(), b"key2");
    assert_eq!(val2.as_bytes(), b"def");
    assert!(iter.next().is_none());
}

#[test]
fn test_options_with_db_operations() {
    let mut opts = Options::new();

    // Set all available options fields
    opts.compression = Compression::Snappy;
    opts.create_if_missing = true;
    opts.error_if_exists = false;
    opts.paranoid_checks = true;
    opts.write_buffer_size = Some(512);
    opts.max_open_files = Some(10);
    opts.block_size = Some(512);
    opts.block_restart_interval = Some(8);
    opts.max_file_size = Some(8 * 1024);

    // Set a bloom filter
    opts.set_bloom_filter(10);
    assert!(opts.filter_policy.is_some());

    // Set a custom comparator
    let comparator = OrdComparator::new("test_comparator");
    opts.set_comparator(comparator);
    assert!(opts.comparator.is_some());

    // Set cache
    opts.cache = Some(Cache::new(1024));
    assert!(opts.cache.is_some());

    // Set logger if feature is enabled
    #[cfg(feature = "logger")]
    {
        struct TestHandler;
        impl LogHandler for TestHandler {
            fn log(&self, _time: SystemTime, _thread_id: &str, _msg: &str) {
                // Simple test logger
            }
        }
        opts.set_logger(Logger::new(TestHandler));
    }

    let tmp = tmpdir("options_test");
    let database = &mut Database::open(tmp.path(), opts).unwrap();

    // Test basic operations
    db_put_simple(database, b"key1", b"abc");
    db_put_simple(database, b"key2", b"def");

    // Test iteration
    let read_opts = ReadOptions::new();
    let mut iter: EntryIterator<'_> = database.iter(read_opts);

    let (key1, val1) = iter.next().unwrap();
    assert_eq!(key1.as_bytes(), b"key1");
    assert_eq!(val1.as_bytes(), b"abc");
    let (key2, val2) = iter.next().unwrap();
    assert_eq!(key2.as_bytes(), b"key2");
    assert_eq!(val2.as_bytes(), b"def");
    assert!(iter.next().is_none());
}

#[test]
fn test_zstd_compression_with_db_operations() {
    let mut opts = Options::new();
    opts.create_if_missing = true;
    opts.compression = Compression::Zstd;

    let tmp = tmpdir("minimal_options_test");
    let database = &mut Database::open(tmp.path(), opts).unwrap();

    // Test basic operations with minimal options
    db_put_simple(database, b"key1", b"abc");
    db_put_simple(database, b"key2", b"def");

    // Test iteration
    let read_opts = ReadOptions::new();
    let mut iter: EntryIterator<'_> = database.iter(read_opts);

    let (key1, val1) = iter.next().unwrap();
    assert_eq!(key1.as_bytes(), b"key1");
    assert_eq!(val1.as_bytes(), b"abc");
    let (key2, val2) = iter.next().unwrap();
    assert_eq!(key2.as_bytes(), b"key2");
    assert_eq!(val2.as_bytes(), b"def");
    assert!(iter.next().is_none());
}
