import 'package:json_annotation/json_annotation.dart';

import '../../../api_response.dart';

part 'timetable_get_week_response.g.dart';

@JsonSerializable(explicitToJson: true)
class McTimetableTeacher {
  final String shortName;
  final String displayName;
  final String? originalShortName;
  final String? originalDisplayName;

  McTimetableTeacher({
    required this.shortName,
    required this.displayName,
    this.originalShortName,
    this.originalDisplayName,
  });

  factory McTimetableTeacher.fromJson(Map<String, dynamic> json) =>
      _$McTimetableTeacherFromJson(json);
  Map<String, dynamic> toJson() => _$McTimetableTeacherToJson(this);
}

@JsonSerializable(explicitToJson: true)
class McTimetableEntry {
  final int id;

  @JsonKey(fromJson: _dateFromJson, toJson: _dateToJson)
  final DateTime date;

  @JsonKey(fromJson: _timeFromJson, toJson: _timeToJson)
  final DateTime startTime;

  @JsonKey(fromJson: _timeFromJson, toJson: _timeToJson)
  final DateTime endTime;

  final List<String> subjects;
  final List<McTimetableTeacher> teachers;
  final List<String> rooms;
  final List<String> classNames;
  final String lessonType;
  final String status;
  final String? substitutionText;
  final String? lessonText;
  final String? infoText;

  McTimetableEntry({
    required this.id,
    required this.date,
    required this.startTime,
    required this.endTime,
    required this.subjects,
    required this.teachers,
    required this.rooms,
    required this.classNames,
    required this.lessonType,
    required this.status,
    required this.substitutionText,
    required this.lessonText,
    required this.infoText,
  });

  factory McTimetableEntry.fromJson(Map<String, dynamic> json) =>
      _$McTimetableEntryFromJson(json);
  Map<String, dynamic> toJson() => _$McTimetableEntryToJson(this);

  /// Combines the calendar date with the hour/minute portion of [startTime]
  /// (which carries a 1970 placeholder date) into a real DateTime.
  DateTime get startDateTime =>
      DateTime(date.year, date.month, date.day, startTime.hour, startTime.minute);

  DateTime get endDateTime =>
      DateTime(date.year, date.month, date.day, endTime.hour, endTime.minute);

  static DateTime _dateFromJson(String raw) => DateTime.parse(raw);
  static String _dateToJson(DateTime d) =>
      '${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}';

  // Backend sends ISO_LOCAL_TIME (e.g. "08:00:00" or "08:00"). Parsed via a
  // fixed-date prefix so we get a real DateTime out of it; only hour/minute
  // are meaningful for rendering.
  static DateTime _timeFromJson(String raw) => DateTime.parse('1970-01-01T$raw');
  static String _timeToJson(DateTime t) =>
      '${t.hour.toString().padLeft(2, '0')}:${t.minute.toString().padLeft(2, '0')}:${t.second.toString().padLeft(2, '0')}';
}

@JsonSerializable(explicitToJson: true)
class TimetableGetWeekResponse extends ApiResponse {
  @JsonKey(fromJson: McTimetableEntry._dateFromJson, toJson: McTimetableEntry._dateToJson)
  final DateTime from;

  @JsonKey(fromJson: McTimetableEntry._dateFromJson, toJson: McTimetableEntry._dateToJson)
  final DateTime until;

  final List<McTimetableEntry> entries;

  TimetableGetWeekResponse({
    required this.from,
    required this.until,
    required this.entries,
  });

  factory TimetableGetWeekResponse.fromJson(Map<String, dynamic> json) =>
      _$TimetableGetWeekResponseFromJson(json);
  Map<String, dynamic> toJson() => _$TimetableGetWeekResponseToJson(this);
}
