import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart';
import 'package:sendtrain/daos/actions_dao.dart';
import 'package:sendtrain/daos/activities_dao.dart';
import 'package:sendtrain/daos/activity_actions_dao.dart';
import 'package:sendtrain/daos/media_items_dao.dart';
import 'package:sendtrain/daos/object_media_items_dao.dart';
import 'package:sendtrain/daos/session_activities_dao.dart';
import 'package:sendtrain/daos/sessions_dao.dart';
import 'package:sendtrain/database/seed.dart';

part 'database.g.dart';

@DriftDatabase(tables: [
  Sessions,
  SessionActivities,
  Activities,
  ActivityActions,
  Actions,
  ObjectMediaItems,
  MediaItems
], daos: [
  SessionsDao,
  ActivitiesDao,
  MediaItemsDao,
  ObjectMediaItemsDao,
  SessionActivitiesDao,
  ActivityActionsDao,
  ActionsDao
])
class AppDatabase extends _$AppDatabase {
  // After generating code, this class needs to define a `schemaVersion` getter
  // and a constructor telling drift where the database should be stored.
  // These are described in the getting started guide: https://drift.simonbinder.eu/setup/
  AppDatabase() : super(_openConnection());

  @override
  int get schemaVersion => 13;

  @override
  MigrationStrategy get migration {
    return MigrationStrategy(
      onCreate: (m) async {
        await m.createAll().then((r) async {
          await seedDb(this);
        }); // create all tables
      },
      beforeOpen: (details) async {
        /// Enable foreign_keys
        await customStatement('PRAGMA foreign_keys = ON');
      },
    );
  }

  static QueryExecutor _openConnection() {
    // `driftDatabase` from `package:drift_flutter` stores the database in
    // `getApplicationDocumentsDirectory()`.
    return driftDatabase(name: 'sendtrain');
  }
}

enum SessionStatus { pending, started, completed, missed }

class Sessions extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 3, max: 32)();
  TextColumn get content => text().named('body')();
  TextColumn get status => textEnum<SessionStatus>()();
  TextColumn get achievements => text().nullable()();
  TextColumn get address => text().withLength(min: 3, max: 256).nullable()();
  DateTimeColumn get date => dateTime().nullable()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

class SessionActivities extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get sessionId => integer().references(Sessions, #id, onDelete: KeyAction.cascade)();
  IntColumn get activityId => integer().references(Activities, #id, onDelete: KeyAction.cascade)();
  IntColumn get position => integer()();
  TextColumn get results => text().nullable()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

enum ActivityCategories { fundamentals, conditioning, advanced, custom, pro }

enum ActivityType {
  strength,
  power,
  conditioning,
  hypertrophy,
  endurance,
  stability,
  mobility,
  flexibility,
  rehabilitation,
  technical
}

class Activities extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 3, max: 32)();
  TextColumn get type => textEnum<ActivityType>()();
  TextColumn get description => text().named('body')();
  TextColumn get category => textEnum<ActivityCategories>()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

class ActivityActions extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get activityId => integer().references(Activities, #id, onDelete: KeyAction.cascade)();
  IntColumn get actionId => integer().references(Actions, #id, onDelete: KeyAction.cascade)();
  IntColumn get position => integer()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

class Actions extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 3, max: 32)();
  TextColumn get description => text().named('body')();
  TextColumn get set => text()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

enum ObjectType {
  actions,
  activities,
  sessions,
}

class ObjectMediaItems extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get objectId => integer()();
  TextColumn get objectType => textEnum<ObjectType>()();
  IntColumn get mediaId => integer().references(MediaItems, #id, onDelete: KeyAction.cascade)();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}

enum MediaType { youtube, image, location, localImage, localVideo }

class MediaItems extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 3, max: 32)();
  TextColumn get description => text().named('body')();
  TextColumn get reference => text()();
  TextColumn get type => textEnum<MediaType>()();
  DateTimeColumn get createdAt =>
      dateTime().withDefault(Variable(DateTime.now()))();
}