import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/api/demo/demo_marianumconnect.dart';
import 'package:marianum_mobile/api/marianumconnect/models/mc_holiday.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/get_breakers/get_breakers_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_schoolyear/timetable_get_schoolyear_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid_response.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';

/// The demo interceptor answers MarianumConnect calls with these bodies; each
/// must round-trip through the same parser the real query uses. A shape
/// mismatch (bare list vs. object) would only surface at runtime otherwise.
void main() {
  Map<String, dynamic> asMap(String path, [Map<String, dynamic> query = const {}]) =>
      DemoMarianumConnect.responseBody(path, query) as Map<String, dynamic>;

  List<Map<String, dynamic>> asList(String path) =>
      (DemoMarianumConnect.responseBody(path, const {}) as List)
          .cast<Map<String, dynamic>>();

  group('DemoMarianumConnect responseBody parses with the real query parser', () {
    test('timetable/me → populated week', () {
      final week = TimetableGetWeekResponse.fromJson(
        asMap('timetable/me', {'from': '2026-05-04', 'until': '2026-05-10'}),
      );
      expect(week.entries, isNotEmpty);
    });

    test('timetable/schoolyear', () {
      expect(
        () => TimetableGetSchoolyearResponse.fromJson(asMap('timetable/schoolyear')),
        returnsNormally,
      );
    });

    test('timetable/rooms → non-empty list of McRoom', () {
      final rooms = asList('timetable/rooms').map(McRoom.fromJson).toList();
      expect(rooms, isNotEmpty);
    });

    test('timetable/subjects → non-empty list of McSubject', () {
      final subjects = asList('timetable/subjects').map(McSubject.fromJson).toList();
      expect(subjects, isNotEmpty);
    });

    test('timetable/timegrid → non-empty list of McTimegridUnit', () {
      final units = asList('timetable/timegrid').map(McTimegridUnit.fromJson).toList();
      expect(units, isNotEmpty);
    });

    test('timetable/holidays → list of McHoliday', () {
      expect(
        () => asList('timetable/holidays').map(McHoliday.fromJson).toList(),
        returnsNormally,
      );
    });

    test('holidays → non-empty list of McHoliday', () {
      final holidays = asList('holidays').map(McHoliday.fromJson).toList();
      expect(holidays, isNotEmpty);
    });

    test('breaker → GetBreakersResponse with no active rules', () {
      final breakers = GetBreakersResponse.fromJson(asMap('breaker'));
      expect(breakers.rules, isEmpty);
    });

    test('foreign element week (timetable/<type>/<id>) parses as a week', () {
      expect(
        () => TimetableGetWeekResponse.fromJson(
          asMap('timetable/teacher/42', {'from': '2026-05-04', 'until': '2026-05-10'}),
        ),
        returnsNormally,
      );
    });

    test('side-effect endpoint returns an empty map body', () {
      expect(asMap('me/telemetry'), isEmpty);
    });
  });
}
