use strict;
use warnings;
use Test::More;
use Test::Exception;
use DBIx::Fast;

eval "use DBD::SQLite 1.74";
plan skip_all => "DBD::SQLite 1.74 required" if $@;

my $db = DBIx::Fast->new(
    dsn        => 'dbi:SQLite:dbname=:memory:',
    driver     => 'SQLite',
    RaiseError => 1,
    PrintError => 0,
);

# Setup tables
$db->exec(q{
    CREATE TABLE users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        email TEXT
    )
});
$db->exec(q{
    CREATE TABLE posts (
        id INTEGER PRIMARY KEY,
        user_id INTEGER,
        title TEXT NOT NULL
    )
});
$db->exec(q{ CREATE INDEX idx_posts_user ON posts(user_id) });
$db->exec(q{ CREATE INDEX idx_posts_title ON posts(title) });

# Insert test data
$db->insert('users', { name => 'Alice', email => 'alice@test.com' });
$db->insert('users', { name => 'Bob',   email => 'bob@test.com'   });
$db->insert('posts', { user_id => 1, title => 'Post 1' });

subtest '_set_tables' => sub {
    my $schema = $db->schema;
    $schema->_set_tables({ fake_table => time() });
    is_deeply(
        [keys %{$schema->tables}],
        ['fake_table'],
        '_set_tables sets tables hash'
    );

    # Restore
    $schema->clear_cache;
    is_deeply($schema->tables, {}, 'Cache cleared after _set_tables');
};

subtest '_load_tables_name' => sub {
    $db->schema->_load_tables_name;
    my $tables = $db->schema->tables;
    ok(exists $tables->{users}, 'users table found');
    ok(exists $tables->{posts}, 'posts table found');
};

subtest 'get_indexes with SQLite' => sub {
    my $indexes = $db->schema->get_indexes('posts');
    ok($indexes, 'Got indexes');
    is(ref $indexes, 'ARRAY', 'Returns arrayref');
    ok(scalar @$indexes >= 1, 'At least one index found');
};

subtest 'get_indexs deprecated alias' => sub {
    # Capture the (deliberate) deprecation warning so it does not leak
    # into the test output.
    my @warnings;
    local $SIG{__WARN__} = sub { push @warnings, @_ };

    my $indexes = $db->schema->get_indexs('posts');
    ok($indexes, 'Deprecated get_indexs works');
    is(ref $indexes, 'ARRAY', 'Returns arrayref');
    ok(grep(/get_indexs is deprecated/, @warnings),
        'deprecation warning emitted');
};

subtest 'get_indexes error - no table' => sub {
    throws_ok { $db->schema->get_indexes(undef) }
        qr/Table required/, 'get_indexes without table throws';
    throws_ok { $db->schema->get_indexes('') }
        qr/Table required/, 'get_indexes with empty string throws';
};

subtest 'primary_keys error - no table' => sub {
    throws_ok { $db->schema->primary_keys(undef) }
        qr/Table name required/, 'primary_keys without table throws';
};

subtest 'table_info error - no table' => sub {
    throws_ok { $db->schema->table_info(undef) }
        qr/Table name required/, 'table_info without table throws';
    throws_ok { $db->schema->table_info() }
        qr/Table name required/, 'table_info with no args throws';
};

subtest 'table_size' => sub {
    my $size = $db->schema->table_size('users');
    ok($size, 'Got table size');
    is(ref $size, 'HASH', 'Returns hashref');
    is($size->{rows}, 2, 'Correct row count');
};

subtest 'table_size error - no table' => sub {
    throws_ok { $db->schema->table_size(undef) }
        qr/Table name required/, 'table_size without table throws';
};

subtest 'primary_keys for table with PK' => sub {
    my $keys = $db->schema->primary_keys('users');
    is_deeply($keys, ['id'], 'Primary key is id');
};

subtest 'table_info for multiple tables' => sub {
    my $user_info = $db->schema->table_info('users');
    my $post_info = $db->schema->table_info('posts');
    ok(scalar @$user_info >= 2, 'users has multiple columns');
    ok(scalar @$post_info >= 2, 'posts has multiple columns');
};

done_testing;
