use strict;
use warnings;

use Test2::V0;
use File::Path qw/make_path/;
use File::Temp qw/tempdir/;

use DBIx::QuickDB::Util qw/disconnect_dbi_handles/;

subtest windows_path_matching => sub {
    ok(
        DBIx::QuickDB::Util::_dbi_name_matches_dir(
            'dbname=C:\\Users\\Smoker\\AppData\\Local\\Temp\\QuickDB\\quickdb',
            'c:/users/smoker/appdata/local/temp/quickdb',
            1,
        ),
        'Windows DBI names match the same directory across slash direction and case',
    );

    ok(
        !DBIx::QuickDB::Util::_dbi_name_matches_dir(
            'dbname=C:\\Users\\Smoker\\AppData\\Local\\Temp\\quickdb-old\\quickdb',
            'c:/users/smoker/appdata/local/temp/quickdb',
            1,
        ),
        'a similarly-named sibling Windows directory does not match',
    );
};

my $has_sqlite = eval { require DBI; require DBD::SQLite; 1 };

subtest multiple_retained_handles => sub {
    plan(skip_all => 'DBI and DBD::SQLite are required for handle cleanup tests')
        unless $has_sqlite;

    my $dir = tempdir(CLEANUP => 1);
    my @dbh = map {
        DBI->connect("dbi:SQLite:dbname=$dir/db$_", '', '', {RaiseError => 1})
    } 1 .. 3;

    ok($_->{Active}, 'retained SQLite handle starts active') for @dbh;

    is(
        disconnect_dbi_handles($dir),
        3,
        'all matching handles were collected and disconnected',
    );
    ok(!$_->{Active}, 'retained SQLite handle was disconnected') for @dbh;
};

subtest pool_never_rebuilds_in_stale_tree => sub {
    require DBIx::QuickDB::Pool;

    my $base  = tempdir(CLEANUP => 1);
    my $cache = "$base/cache with space";
    make_path($cache);
    my $dir   = "$cache/database-checksum";
    make_path($dir);
    open(my $fh, '>', "$dir/old-schema") or die "Could not create stale marker: $!";
    print {$fh} "stale\n";
    close($fh);

    my $pool = DBIx::QuickDB::Pool->new(cache_dir => $cache);
    my $spec = {};

    my $real_remove = \&DBIx::QuickDB::Pool::remove_tree_robust;
    my $calls = 0;
    no warnings qw/redefine once/;
    local *DBIx::QuickDB::Pool::remove_tree_robust = sub {
        my ($path) = @_;
        return 0 if $path eq $dir && !$calls++;
        return $real_remove->(@_);
    };

    # Stop after directory preparation; this unit test does not need a driver.
    local *DBIx::QuickDB::Pool::build_via_driver = sub { die "PREPARED\n" };
    my $ok = eval { $pool->build_db($dir, $spec); 1 };
    my $err = $@;

    ok(!$ok, 'test hook stopped the build after directory preparation');
    like($err, qr/^PREPARED/, 'reached the builder with a prepared directory');
    ok(-d $dir, 'fresh canonical build directory was created');
    ok(!-e "$dir/old-schema", 'stale content was not left in the build directory');

    my $quarantines = sub {
        opendir(my $dh, $cache) or die "Could not open cache directory: $!";
        my @paths = map { "$cache/$_" }
            grep { /^database-checksum\.STALE-/ && -d "$cache/$_" }
            readdir($dh);
        closedir($dh);
        return @paths;
    };

    my @quarantine = $quarantines->();
    is(scalar(@quarantine), 1, 'failed deletion quarantined exactly one stale tree');
    ok(-e "$quarantine[0]/old-schema", 'quarantine contains the stale content');

    $pool->clear_old_cache(0);
    is([$quarantines->()], [], 'a later cache sweep reclaims the quarantine from a path with spaces');
};

done_testing;
