import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:household_keeper/core/providers/database_provider.dart';
import 'package:household_keeper/features/home/domain/calendar_models.dart';
import 'package:household_keeper/features/home/domain/daily_plan_models.dart';
import 'package:household_keeper/features/tasks/domain/task_sort_option.dart';
import 'package:household_keeper/features/tasks/presentation/sort_preference_notifier.dart';

/// Notifier that manages the currently selected date in the calendar strip.
///
/// Defaults to today (start of day, time zeroed out).
/// NOT autoDispose — the selected date persists while the app is alive.
class SelectedDateNotifier extends Notifier<DateTime> {
  @override
  DateTime build() {
    final now = DateTime.now();
    return DateTime(now.year, now.month, now.day);
  }

  /// Update the selected date (always normalized to start of day).
  void selectDate(DateTime date) {
    state = DateTime(date.year, date.month, date.day);
  }
}

/// Provider for the currently selected date in the calendar strip.
final selectedDateProvider =
    NotifierProvider<SelectedDateNotifier, DateTime>(
  SelectedDateNotifier.new,
);

/// Sort a list of [TaskWithRoom] by the given [sortOption].
///
/// Returns a new sorted list; never mutates the original.
/// Only [dayTasks] are sorted — the overdue section stays in its existing
/// order per user decision.
List<TaskWithRoom> _sortTasks(
  List<TaskWithRoom> tasks,
  TaskSortOption sortOption,
) {
  final sorted = List<TaskWithRoom>.from(tasks);
  switch (sortOption) {
    case TaskSortOption.alphabetical:
      sorted.sort((a, b) => a.task.name.toLowerCase().compareTo(
            b.task.name.toLowerCase(),
          ));
    case TaskSortOption.interval:
      sorted.sort((a, b) {
        final cmp = a.task.intervalType.index.compareTo(
          b.task.intervalType.index,
        );
        if (cmp != 0) return cmp;
        return a.task.intervalDays.compareTo(b.task.intervalDays);
      });
    case TaskSortOption.effort:
      sorted.sort((a, b) => a.task.effortLevel.index.compareTo(
            b.task.effortLevel.index,
          ));
  }
  return sorted;
}

/// Reactive calendar day state: tasks for the selected date + overdue tasks.
///
/// Overdue tasks are only included when the selected date is today.
/// Past and future dates show only tasks originally due on that day.
///
/// dayTasks are sorted in-memory according to the active [sortPreferenceProvider].
/// overdueTasks retain their existing order (pinned at top, unsorted per design).
///
/// Defined manually (not @riverpod) because riverpod_generator has trouble
/// with drift's generated [Task] type. Same pattern as [dailyPlanProvider].
final calendarDayProvider =
    StreamProvider.autoDispose<CalendarDayState>((ref) {
  final db = ref.watch(appDatabaseProvider);
  final selectedDate = ref.watch(selectedDateProvider);
  final sortOption = ref.watch(sortPreferenceProvider);

  final now = DateTime.now();
  final today = DateTime(now.year, now.month, now.day);
  final isToday = selectedDate == today;

  final dayTasksStream = db.calendarDao.watchTasksForDate(selectedDate);

  return dayTasksStream.asyncMap((dayTasks) async {
    final List<TaskWithRoom> overdueTasks;

    if (isToday) {
      // When viewing today, include overdue tasks (due before today)
      overdueTasks =
          await db.calendarDao.watchOverdueTasks(selectedDate).first;
    } else {
      // Past or future dates: no overdue carry-over
      overdueTasks = const [];
    }

    final totalTaskCount = await db.calendarDao.getTaskCount();

    return CalendarDayState(
      selectedDate: selectedDate,
      dayTasks: _sortTasks(dayTasks, sortOption),
      overdueTasks: overdueTasks,
      totalTaskCount: totalTaskCount,
    );
  });
});

/// Room-scoped calendar day state: tasks for the selected date within a room.
///
/// Mirrors [calendarDayProvider] but filters by [roomId].
/// Uses the shared [selectedDateProvider] so date selection is consistent
/// across HomeScreen and room views.
final roomCalendarDayProvider =
    StreamProvider.autoDispose.family<CalendarDayState, int>((ref, roomId) {
  final db = ref.watch(appDatabaseProvider);
  final selectedDate = ref.watch(selectedDateProvider);
  final sortOption = ref.watch(sortPreferenceProvider);

  final now = DateTime.now();
  final today = DateTime(now.year, now.month, now.day);
  final isToday = selectedDate == today;

  final dayTasksStream =
      db.calendarDao.watchTasksForDateInRoom(selectedDate, roomId);

  return dayTasksStream.asyncMap((dayTasks) async {
    final List<TaskWithRoom> overdueTasks;

    if (isToday) {
      overdueTasks = await db.calendarDao
          .watchOverdueTasksInRoom(selectedDate, roomId)
          .first;
    } else {
      overdueTasks = const [];
    }

    final totalTaskCount = await db.calendarDao.getTaskCountInRoom(roomId);

    return CalendarDayState(
      selectedDate: selectedDate,
      dayTasks: _sortTasks(dayTasks, sortOption),
      overdueTasks: overdueTasks,
      totalTaskCount: totalTaskCount,
    );
  });
});
