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

import '../../features/home/data/calendar_dao.dart';
import '../../features/home/data/daily_plan_dao.dart';
import '../../features/rooms/data/rooms_dao.dart';
import '../../features/tasks/data/tasks_dao.dart';
import '../../features/tasks/domain/effort_level.dart';
import '../../features/tasks/domain/frequency.dart';

part 'database.g.dart';

/// Rooms table: each room has a name, icon, and sort order.
class Rooms extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get name => text().withLength(min: 1, max: 100)();
  TextColumn get iconName => text()();
  IntColumn get sortOrder => integer().withDefault(const Constant(0))();
  DateTimeColumn get createdAt =>
      dateTime().clientDefault(() => DateTime.now())();
}

/// Tasks table: each task belongs to a room and has scheduling info.
class Tasks extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get roomId => integer().references(Rooms, #id)();
  TextColumn get name => text().withLength(min: 1, max: 200)();
  TextColumn get description => text().nullable()();
  IntColumn get intervalType => intEnum<IntervalType>()();
  IntColumn get intervalDays =>
      integer().withDefault(const Constant(1))();
  IntColumn get anchorDay => integer().nullable()();
  IntColumn get effortLevel => intEnum<EffortLevel>()();
  DateTimeColumn get nextDueDate => dateTime()();
  DateTimeColumn get createdAt =>
      dateTime().clientDefault(() => DateTime.now())();
  BoolColumn get isActive =>
      boolean().withDefault(const Constant(true))();
}

/// TaskCompletions table: records when a task was completed.
class TaskCompletions extends Table {
  IntColumn get id => integer().autoIncrement()();
  IntColumn get taskId => integer().references(Tasks, #id)();
  DateTimeColumn get completedAt => dateTime()();
}

@DriftDatabase(
  tables: [Rooms, Tasks, TaskCompletions],
  daos: [RoomsDao, TasksDao, DailyPlanDao, CalendarDao],
)
class AppDatabase extends _$AppDatabase {
  AppDatabase([QueryExecutor? executor])
      : super(executor ?? _openConnection());

  @override
  int get schemaVersion => 3;

  @override
  MigrationStrategy get migration {
    return MigrationStrategy(
      onCreate: (Migrator m) async {
        await m.createAll();
      },
      onUpgrade: (Migrator m, int from, int to) async {
        if (from < 2) {
          await m.createTable(rooms);
          await m.createTable(tasks);
          await m.createTable(taskCompletions);
        }
        if (from == 2) {
          await m.addColumn(tasks, tasks.isActive);
        }
      },
      beforeOpen: (details) async {
        await customStatement('PRAGMA foreign_keys = ON');
      },
    );
  }

  static QueryExecutor _openConnection() {
    return driftDatabase(
      name: 'household_keeper',
      native: const DriftNativeOptions(
        databaseDirectory: getApplicationSupportDirectory,
      ),
    );
  }
}
