// https://docs.flutter.dev/cookbook/persistence/sqlite

// SQLite
import 'dart:io';
import 'dart:async';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

// Local
import '/models/expense.dart';
import '/models/tracked_item.dart';

// Leaned on this example:
//   https://learnflutterwithme.com/sqlite
class DatabaseHelper {
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  static Database? _db;
  Future<Database> get db async => _db ??= await _initDatabase();

  Future<Database> _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, "com_hyperling_expense.db");
    return await openDatabase(
      path,
      version: 2,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  Future _onCreate(Database db, int version) async {
    await db.execute("""
      CREATE TABLE expense
        ( id INTEGER PRIMARY KEY
        , name TEXT NOT NULL UNIQUE
        , cost DOUBLE NOT NULL
        , frequency TEXT NOT NULL
        , description TEXT
      )
      """);
  }

  Future _onUpgrade(Database db, int previousVersion, int newVersion) async {
    // Added in DB version 2.
    if (previousVersion < 2 && newVersion >= 2) {
      await db.execute("""
        CREATE TABLE income
          ( id INTEGER PRIMARY KEY
          , name TEXT NOT NULL UNIQUE
          , revenue DOUBLE NOT NULL
          , frequency TEXT NOT NULL
          , description TEXT
        )
        """);
      await db.execute("""
        CREATE TABLE asset
          ( id INTEGER PRIMARY KEY
          , name TEXT NOT NULL UNIQUE
          , amount DOUBLE NOT NULL
          , description TEXT
        )
        """);
    }
  }

  /// Expense Section
  ///
  Future<List<Expense>> getExpenses() async {
    Database db = await instance.db;
    var expenses = await db.query("expense", orderBy: "name");
    List<Expense> expenseList = expenses.isNotEmpty
        ? expenses.map((c) => Expense.fromMap(c)).toList()
        : [];
    return expenseList;
  }

  Future<int> addExpense(TrackedItem expense) async {
    Database db = await instance.db;
    return await db.insert(
      "expense",
      expense.toMap(),
    );
  }

  Future<int> removeExpense(int id) async {
    Database db = await instance.db;
    return await db.delete(
      "expense",
      where: "id = ?",
      whereArgs: [id],
    );
  }

  Future<int> updateExpense(TrackedItem expense) async {
    Database db = await instance.db;
    return await db.update(
      "expense",
      expense.toMap(),
      where: "id = ?",
      whereArgs: [expense.id],
    );
  }

  Future<bool> checkExpenseNameExists(String name) async {
    Database db = await instance.db;
    var expenses = await db.query(
      "expense",
      where: "name = ?",
      whereArgs: [name],
    );
    return expenses.isNotEmpty;
  }

  ///

  /// Income Section
  ///

  ///
  /// Liquid Asset Section

  ///
}