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

import 'sync_log_type_enum.dart';
import 'time_frame_enum.dart';

part 'drift_database.g.dart';

/// Eine Tabelle für Konten.
class Accounts extends Table {
  /// Eindeutige ID des Kontos
  IntColumn get id => integer().autoIncrement()();

  /// Name des Kontos
  TextColumn get name => text().withDefault(const Constant(''))();

  /// Der externe Identifier, wenn woanders gespeichert
  IntColumn get externalIdentifier => integer().nullable()();

  /// Wann das Konto das letzte mal geupdated wurde
  DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
}

/// Eine Tabelle für einzelne Transaktionen.
class Transactions extends Table {
  /// Eindeutige ID der Transaktion
  IntColumn get id => integer().autoIncrement()();

  /// Name/Beschreibung der Transaktion
  TextColumn get name => text().withDefault(const Constant(''))();

  /// Datum der Transaktion
  DateTimeColumn get date => dateTime().nullable()();

  /// Betrag der Transaktion
  RealColumn get amount => real().withDefault(const Constant(0))();

  /// Ob diese Transaktion bereits geprüft wurde
  BoolColumn get checked => boolean().withDefault(const Constant(true))();

  /// Fremdschlüssel zum zugehörigen Konto
  IntColumn get accountId => integer().references(Accounts, #id)();

  /// Fremdschlüssel zur zugehörigen wiederkehrenden Transaktion,
  /// falls vorhanden
  IntColumn get recurringTransactionId =>
      integer().nullable().references(RecurringTransactions, #id)();

  /// Der externe Identifier, wenn woanders gespeichert
  IntColumn get externalIdentifier => integer().nullable()();

  /// Wann die Transaktion das letzte mal geupdated wurde
  DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
}

/// Eine Tabelle für wiederkehrende Transaktionen.
class RecurringTransactions extends Table {
  /// Eindeutige ID der wiederkehrenden Transaktion
  IntColumn get id => integer().autoIncrement()();

  /// Name/Beschreibung der wiederkehrenden Transaktion
  TextColumn get name => text().withDefault(const Constant(''))();

  /// Startdatum der wiederkehrenden Transaktion
  DateTimeColumn get startDate => dateTime().nullable()();

  /// Zeitlicher Rahmen für die Wiederholung
  IntColumn get timeFrame => intEnum<TimeFrameEnum>()();

  /// Betrag der wiederkehrenden Transaktion
  RealColumn get amount => real().withDefault(const Constant(0))();

  /// Fremdschlüssel zum zugehörigen Konto
  IntColumn get accountId => integer().references(Accounts, #id)();

  /// Der externe Identifier, wenn woanders gespeichert
  IntColumn get externalIdentifier => integer().nullable()();

  /// Wann die wiederkehrende Transaktion das letzte mal geupdated wurde
  DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
}

/// Eine Tabelle um den Status der Synchronisation zu loggen
class SyncLog extends Table {
  /// Eindeutige ID des SyncLogs
  IntColumn get id => integer().autoIncrement()();

  /// Der Typ des SyncLogs
  IntColumn get type => intEnum<SyncLogTypeEnum>()();

  /// Die Beschreibung der Eintragung des SyncLogs
  TextColumn get description => text().withDefault(const Constant(''))();

  /// Wann dieser SyncLog das letzte mal geupdated wurde
  DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
}

/// Hauptklasse für die Drift-Datenbank der Anwendung.
@DriftDatabase(tables: [Accounts, Transactions, RecurringTransactions, SyncLog])
class AppDatabase extends _$AppDatabase {
  /// Erstellt eine neue Datenbankinstanz
  AppDatabase() : super(_openConnection());

  @override
  int get schemaVersion => 1;

  /// Öffnet die Datenbankverbindung
  static QueryExecutor _openConnection() => driftDatabase(
    name: 'dragon_ledger',
    web: DriftWebOptions(
      sqlite3Wasm: Uri.parse('sqlite3.wasm'),
      driftWorker: Uri.parse('drift_worker.js'),
    ),
      native: const DriftNativeOptions(shareAcrossIsolates: true)
  );
}
