import 'dart:convert';

import 'package:drift/drift.dart';
import 'package:drift/web.dart';

import 'package:test/test.dart';

// Created from an empty sqlite file with
// `CREATE TABLE foo (name TEXT)`
// `INSERT INTO foo ('hello world')`
const _rawDataBase64 = '''
[encoded data, 11050 characters]
AAAAAAAAAAAAAAAAAAAAAAANAQIjaGVsbG8gd29ybGQ=
''';

void main() {
  test('can initialize database when absent', () async {
    await _testWith(const DriftWebStorage('name'));
  });

  test('can initialize database when absent - IndexedDB', () async {
    await _testWith(
        DriftWebStorage.indexedDb('name', migrateFromLocalStorage: false));
  });

  test('runs setup callback', () async {
    final executor = WebDatabase.withStorage(
      DriftWebStorage.volatile(),
      setup: expectAsync1(
        (database) {
          database.run('CREATE TABLE IF NOT EXISTS foo (bar, baz);');
        },
        // One for open, one because the database is closed and re-opened after
        // data is written.
        count: 2,
      ),
    );

    driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
    final attachedDb = _FakeDatabase(executor);

    await executor.ensureOpen(attachedDb);
    await executor.runSelect('SELECT * FROM foo;', []);
  });
}

Future<void> _testWith(DriftWebStorage storage) async {
  var didCallInitializer = false;
  final executor = WebDatabase.withStorage(storage, initializer: () async {
    didCallInitializer = true;
    return base64.decode(_rawDataBase64.replaceAll('\n', ''));
  });

  driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
  final attachedDb = _FakeDatabase(executor);

  await executor.ensureOpen(attachedDb);
  expect(didCallInitializer, isTrue);

  final result = await executor.runSelect('SELECT * FROM foo', const []);
  expect(result, [
    {'name': 'hello world'}
  ]);

  await executor.close();
}

class _FakeDatabase extends GeneratedDatabase {
  _FakeDatabase(QueryExecutor executor) : super(executor);

  @override
  Iterable<TableInfo<Table, DataClass>> get allTables => const [];

  @override
  int get schemaVersion => 1;
}
