import 'package:hub/shared/utils/cache_util.dart'; import 'package:sqflite/sqflite.dart'; import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; class DatabaseConfig { static const String dbName = 'database.db'; static const int dbVersion = 1; static const String tableKeychain = 'keychain'; static const String columnKey = 'key'; static const String columnValue = 'value'; static const String columnType = 'type'; static const String columnUpdateAt = 'updateAt'; static const String columnResolvedAt = 'resolvedAt'; static const String columnCreatedAt = 'createdAt'; static const List> initialData = [ {'key': 'devUUID', 'value': '', 'type': 'user'}, {'key': 'userUUID', 'value': '', 'type': 'user'}, {'key': 'userDevUUID', 'value': '', 'type': 'user'}, {'key': 'status', 'value': '', 'type': 'user'}, {'key': 'userName', 'value': '', 'type': 'user'}, {'key': 'cliUUID', 'value': '', 'type': 'local'}, {'key': 'ownerUUID', 'value': '', 'type': 'local'}, {'key': 'cliName', 'value': '', 'type': 'local'}, {'key': 'whatsapp', 'value': 'false', 'type': 'util'}, {'key': 'provisional', 'value': 'false', 'type': 'util'}, {'key': 'pets', 'value': 'false', 'type': 'util'}, {'key': 'local', 'value': 'false', 'type': 'util'}, {'key': 'notify', 'value': 'false', 'type': 'util'}, {'key': 'fingerprint', 'value': 'false', 'type': 'util'}, {'key': 'access', 'value': 'false', 'type': 'util'}, {'key': 'panic', 'value': 'false', 'type': 'util'}, {'key': 'person', 'value': 'false', 'type': 'util'}, {'key': 'requestOSnotification', 'value': 'false', 'type': 'util'}, {'key': 'petAmountRegister', 'value': '', 'type': 'local'}, ]; } class SQLiteStorageHelper { static final SQLiteStorageHelper _instance = SQLiteStorageHelper._internal(); static Database? _database; static String? _databasePath; factory SQLiteStorageHelper() => _instance; SQLiteStorageHelper._internal(); Future get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future _getDatabasePath() async { if (_databasePath != null) return _databasePath!; final databasesPath = await getDatabasesPath(); _databasePath = join(databasesPath, DatabaseConfig.dbName); log('Database path: $_databasePath'); return _databasePath!; } Future _initDatabase() async { final path = await _getDatabasePath(); return await openDatabase( path, version: DatabaseConfig.dbVersion, onCreate: _onCreate, onOpen: _onOpen, onUpgrade: _onUpgrade, onDowngrade: _onDowngrade, onConfigure: _onConfigure, ).catchError((error) { log('Error initializing database: $error'); throw error; }).whenComplete(() async => await setupLocalVariables()); } Future _onCreate(Database db, int version) async { log('Creating tables...'); await db.execute(''' CREATE TABLE ${DatabaseConfig.tableKeychain} ( ${DatabaseConfig.columnKey} TEXT UNIQUE, ${DatabaseConfig.columnValue} TEXT, ${DatabaseConfig.columnType} TEXT, ${DatabaseConfig.columnUpdateAt} TEXT, ${DatabaseConfig.columnResolvedAt} TEXT, ${DatabaseConfig.columnCreatedAt} TEXT ); '''); await _insertInitialData(db); log('Tables created'); } Future _insertInitialData(Database db) async { final batch = db.batch(); for (var data in DatabaseConfig.initialData) { batch.insert(DatabaseConfig.tableKeychain, data); } await batch.commit(noResult: true); } Future _onOpen(Database db) async { log('Checking existing data...'); await _checkExistingData(db); } Future _onUpgrade(Database db, int oldVersion, int newVersion) async { log('Upgrading database from version $oldVersion to $newVersion'); } Future _onDowngrade(Database db, int oldVersion, int newVersion) async { log('Downgrading database from version $oldVersion to $newVersion'); } Future _onConfigure(Database db) async { log('Configuring database...'); } Future _checkExistingData(Database db) async { try { final maps = await db.query(DatabaseConfig.tableKeychain); log('Existing data: $maps'); } catch (error) { log('Error checking existing data: $error'); } } String _devUUID = ''; String _userUUID = ''; String _userDevUUID = ''; String _status = ''; String _userName = ''; String _cliUUID = ''; String _ownerUUID = ''; String _cliName = ''; String _petAmountRegister = ''; bool _whatsapp = false; bool _provisional = false; bool _pets = false; bool _local = false; bool _notify = false; bool _fingerprint = false; bool _access = false; bool _panic = false; bool _person = false; bool _requestOSnotification = false; String get createdAt => '0000-00-00 00:00:00'; String get devUUID => _devUUID; String get userUUID => _userUUID; String get userDevUUID => _userDevUUID; String get status => _status; String get userName => _userName; String get cliUUID => _cliUUID; String get ownerUUID => _ownerUUID; String get cliName => _cliName; String get petAmountRegister => _petAmountRegister; bool get whatsapp => _whatsapp; bool get provisional => _provisional; bool get pets => _pets; bool get local => _local; bool get notify => _notify; bool get fingerprint => _fingerprint; bool get access => _access; bool get panic => _panic; bool get person => _person; bool get requestOSnotification => _requestOSnotification; set devUUID(String value) => set('devUUID', value); set userUUID(String value) => set('userUUID', value); set userDevUUID(String value) => set('userDevUUID', value); set status(String value) => set('status', value); set userName(String value) => set('userName', value); set cliUUID(String value) => set('cliUUID', value); set ownerUUID(String value) => set('ownerUUID', value); set cliName(String value) => set('cliName', value); set petAmountRegister(String value) => set('petAmountRegister', value); set whatsapp(bool value) => set('whatsapp', value); set provisional(bool value) => set('provisional', value); set pets(bool value) => set('pets', value); set local(bool value) => set('local', value); set notify(bool value) => set('notify', value); set fingerprint(bool value) => set('fingerprint', value); set access(bool value) => set('access', value); set panic(bool value) => set('panic', value); set person(bool value) => set('person', value); set requestOSnotification(bool value) => set('requestOSnotification', value); Future setupLocalVariables() async { log('Setting up local variables...'); await _database?.transaction((txn) async { final keys = [ 'devUUID', 'userUUID', 'userDevUUID', 'status', 'userName', 'cliUUID', 'ownerUUID', 'cliName', 'whatsapp', 'provisional', 'pets', 'local', 'notify', 'fingerprint', 'access', 'panic', 'person', 'requestOSnotification' ]; final results = await Future.wait(keys.map((key) => get(key))); _devUUID = results[0]?.toString() ?? ''; _userUUID = results[1]?.toString() ?? ''; _userDevUUID = results[2]?.toString() ?? ''; _status = results[3]?.toString() ?? ''; _userName = results[4]?.toString() ?? ''; _cliUUID = results[5]?.toString() ?? ''; _ownerUUID = results[6]?.toString() ?? ''; _cliName = results[7]?.toString() ?? ''; _whatsapp = results[8] == 'true'; _provisional = results[9] == 'true'; _pets = results[10] == 'true'; _local = results[11] == 'true'; _notify = results[12] == 'true'; _fingerprint = results[13] == 'true'; _access = results[14] == 'true'; _panic = results[15] == 'true'; _person = results[16] == 'true'; _requestOSnotification = results[17] == 'true'; }); } Future getBoolean(String key) async { final value = await get(key); return value == 'true'; } Future get(String key) async { final cachedValue = CacheUtil.get(key); if (cachedValue != null) { return cachedValue; } try { final db = await database; final result = await db.query( DatabaseConfig.tableKeychain, columns: [DatabaseConfig.columnValue], where: '${DatabaseConfig.columnKey} = ?', whereArgs: [key], ); if (result.isNotEmpty) { final value = result.first[DatabaseConfig.columnValue]; CacheUtil.set(key, value); return value; } return null; } catch (error) { log('Error getting value for key $key: $error'); return null; } } Future set(String key, dynamic value) async { CacheUtil.set(key, value); final db = await database; final data = { DatabaseConfig.columnKey: key, DatabaseConfig.columnValue: value.toString(), DatabaseConfig.columnUpdateAt: DateTime.now().toIso8601String(), DatabaseConfig.columnCreatedAt: DateTime.now().toIso8601String(), }; return await db.insert( DatabaseConfig.tableKeychain, data, conflictAlgorithm: ConflictAlgorithm.replace, ); } Future delete(String key) async { final db = await database; return await db.transaction((txn) async { return await txn.delete( DatabaseConfig.tableKeychain, where: '${DatabaseConfig.columnKey} = ?', whereArgs: [key], ); }); } Future purge() async { await deleteDatabaseDB(); await database; log('Database purged'); } Future deleteDatabaseDB() async { final path = await _getDatabasePath(); await deleteDatabase(path); log('Database deleted'); _database = null; } }