import 'package:flutter/material.dart';

import '../../../../api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid_response.dart';
import '../../../../state/app/modules/timetable/bloc/timetable_state.dart';

class LessonPeriod {
  final String name;
  final TimeOfDay start;
  final TimeOfDay end;
  final bool isBreak;

  const LessonPeriod({
    required this.name,
    required this.start,
    required this.end,
    this.isBreak = false,
  });

  Duration get duration => Duration(
    minutes: (end.hour * 60 + end.minute) - (start.hour * 60 + start.minute),
  );

  int get _startMinutes => start.hour * 60 + start.minute;
}

class LessonPeriodSchedule {
  final List<LessonPeriod> periods;

  const LessonPeriodSchedule(this.periods);

  static LessonPeriodSchedule? fromApi(TimetableGetTimegridResponse response) {
    // The Marianum-Connect endpoint returns one entry per (weekday, unit). The
    // school's bell schedule is identical Mon–Fri, so we pick Monday as the
    // canonical day and fall back to the first available weekday if Monday is
    // missing.
    final monday = response.result
        .where((u) => u.dayOfWeek == McDayOfWeek.monday)
        .toList();
    final source = monday.isNotEmpty ? monday : response.result;
    if (source.isEmpty) return null;

    final periods =
        source
            .map(
              (u) => LessonPeriod(
                name: u.label,
                start: TimeOfDay(
                  hour: u.startTime.hour,
                  minute: u.startTime.minute,
                ),
                end: TimeOfDay(
                  hour: u.endTime.hour,
                  minute: u.endTime.minute,
                ),
              ),
            )
            .toList()
          ..sort((a, b) => a._startMinutes.compareTo(b._startMinutes));

    return LessonPeriodSchedule(periods);
  }

  static LessonPeriodSchedule fallback() => const LessonPeriodSchedule([
    LessonPeriod(
      name: '0',
      start: TimeOfDay(hour: 7, minute: 10),
      end: TimeOfDay(hour: 7, minute: 53),
    ),
    LessonPeriod(
      name: '1',
      start: TimeOfDay(hour: 7, minute: 55),
      end: TimeOfDay(hour: 8, minute: 40),
    ),
    LessonPeriod(
      name: '2',
      start: TimeOfDay(hour: 8, minute: 40),
      end: TimeOfDay(hour: 9, minute: 25),
    ),
    LessonPeriod(
      name: '3',
      start: TimeOfDay(hour: 9, minute: 30),
      end: TimeOfDay(hour: 10, minute: 15),
    ),
    LessonPeriod(
      name: '4',
      start: TimeOfDay(hour: 10, minute: 35),
      end: TimeOfDay(hour: 11, minute: 20),
    ),
    LessonPeriod(
      name: '5',
      start: TimeOfDay(hour: 11, minute: 25),
      end: TimeOfDay(hour: 12, minute: 10),
    ),
    LessonPeriod(
      name: '6',
      start: TimeOfDay(hour: 12, minute: 15),
      end: TimeOfDay(hour: 13, minute: 0),
    ),
    LessonPeriod(
      name: '7',
      start: TimeOfDay(hour: 13, minute: 5),
      end: TimeOfDay(hour: 13, minute: 50),
    ),
    LessonPeriod(
      name: '8',
      start: TimeOfDay(hour: 14, minute: 5),
      end: TimeOfDay(hour: 14, minute: 50),
    ),
    LessonPeriod(
      name: '9',
      start: TimeOfDay(hour: 14, minute: 50),
      end: TimeOfDay(hour: 15, minute: 35),
    ),
    LessonPeriod(
      name: '10',
      start: TimeOfDay(hour: 15, minute: 40),
      end: TimeOfDay(hour: 16, minute: 25),
    ),
    LessonPeriod(
      name: '11',
      start: TimeOfDay(hour: 16, minute: 25),
      end: TimeOfDay(hour: 17, minute: 10),
    ),
  ]);

  static LessonPeriodSchedule fromState(TimetableState state) {
    final fromApi = state.timegrid != null
        ? LessonPeriodSchedule.fromApi(state.timegrid!)
        : null;
    return (fromApi ?? fallback()).withSyntheticBreaks();
  }

  LessonPeriodSchedule withSyntheticBreaks() {
    final result = <LessonPeriod>[];
    for (var i = 0; i < periods.length; i++) {
      final current = periods[i];
      result.add(current);
      if (i + 1 >= periods.length) continue;
      final next = periods[i + 1];
      final gapMinutes =
          next._startMinutes - (current.end.hour * 60 + current.end.minute);
      if (gapMinutes >= 10) {
        result.add(
          LessonPeriod(
            name: 'Pause',
            start: current.end,
            end: next.start,
            isBreak: true,
          ),
        );
      }
    }
    return LessonPeriodSchedule(result);
  }
}
