part of 'schedule_bloc.dart';

@immutable
class ScheduleState {
  const ScheduleState({
    this.schedules = const {},
    this.tempSchedules = const [],
    this.selectedDates = const [],
    this.prevSelectedDates = const [],
    this.selectedSchedules = const [],
    this.status = StateStatus.idle,
    this.isInEditMode = false,
    this.isScheduleAddMode = false,
    this.scheduleErrorText = '',
  });

  final Map<String, DaySchedule> schedules;
  final List<DaySchedule> tempSchedules;
  final List<DateTime> selectedDates;
  final List<DateTime> prevSelectedDates;
  final List<DaySchedule> selectedSchedules;
  final StateStatus status;
  final bool isInEditMode;
  final bool isScheduleAddMode;
  final String scheduleErrorText;

  Future<bool> get isValid async {
    if (tempSchedules.isEmpty) return false;
    bool isValid = true;

    for (int i = 0; i < tempSchedules.length; i++) {
      isValid = tempSchedules[i].isValid;

      if (!isValid) return isValid;
    }

    return isValid;
  }

  ScheduleState copyWith({
    Map<String, DaySchedule>? schedules,
    List<DaySchedule>? tempSchedules,
    List<DateTime>? selectedDates,
    List<DateTime>? prevSelectedDates,
    List<DaySchedule>? selectedSchedules,
    StateStatus? status,
    bool? isInEditMode,
    bool? isScheduleAddMode,
    String? scheduleErrorText,
  }) {
    return ScheduleState(
      schedules: schedules ?? this.schedules,
      tempSchedules: tempSchedules ?? this.tempSchedules,
      selectedDates: selectedDates ?? this.selectedDates,
      prevSelectedDates: prevSelectedDates ?? this.prevSelectedDates,
      selectedSchedules: selectedSchedules ?? this.selectedSchedules,
      status: status ?? this.status,
      isInEditMode: isInEditMode ?? this.isInEditMode,
      isScheduleAddMode: isScheduleAddMode ?? this.isScheduleAddMode,
      scheduleErrorText: scheduleErrorText ?? this.scheduleErrorText,
    );
  }

  DaySchedule? findScheduleForDate(DateTime date) {
    return schedules[date.getDayDateId()] ?? schedules[date.getWeekdayId()];
  }

  bool containsScheduleForDate(DateTime date) {
    return schedules.containsKey(date.getDayDateId()) ||
        schedules.containsKey(date.getWeekdayId());
  }

  Future<List<DaySchedule>> findSchedulesForSelection() async {
    return [
      for (final date in selectedDates)
        if (schedules.containsKey(date.getDayDateId()))
          schedules[date.getDayDateId()]!
        else if (schedules.containsKey(date.getWeekdayId()))
          schedules[date.getWeekdayId()]!.copyWith(
            date: date,
          ),
    ];
  }

  List<DaySchedule> getDailySchedulesForTemporary() {
    return [
      for (final day in tempSchedules)
        if (schedules.containsKey(day.getIdKey())) schedules[day.getIdKey()]!
    ];
  }

  bool isRangeContainsSchedules(List<DateTime> dates) {
    return dates.any(
      (date) => schedules.containsKey(date.getDayDateId()),
    );
  }

  DaySchedule getScheduleForDate({
    required DateTime date,
    required bool isWeekly,
  }) {
    final daySchedule =
        schedules[isWeekly ? date.getWeekdayId() : date.getDayDateId()];

    return daySchedule ??
        DaySchedule(
          date: date,
          slots: const [],
          isWeekly: isWeekly,
        );
  }

  Map<String, DaySchedule> mergeSchedules() {
    final schedules = Map<String, DaySchedule>.from(this.schedules);

    for (final schedule in tempSchedules) {
      schedules[schedule.getIdKey()] = schedule;
    }

    return schedules;
  }
}
