import 'dart:async';

import 'package:bottom_sheet/bottom_sheet.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
import 'package:provider/provider.dart';
import 'package:rrule/rrule.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';

import '../../../api/mhsl/customTimetableEvent/customTimetableEvent.dart';
import '../../../api/mhsl/customTimetableEvent/remove/removeCustomTimetableEvent.dart';
import '../../../api/mhsl/customTimetableEvent/remove/removeCustomTimetableEventParams.dart';
import '../../../api/webuntis/queries/getRooms/getRoomsResponse.dart';
import '../../../api/webuntis/queries/getSubjects/getSubjectsResponse.dart';
import '../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
import '../../../model/timetable/timetableProps.dart';
import '../../../widget/centeredLeading.dart';
import '../../../widget/confirmDialog.dart';
import '../../../widget/debug/debugTile.dart';
import '../../../widget/unimplementedDialog.dart';
import '../more/roomplan/roomplan.dart';
import 'arbitraryAppointment.dart';
import 'customTimetableEventEditDialog.dart';

class AppointmentDetails {
  static String _getEventPrefix(String? code) {
    if(code == 'cancelled') return 'Entfällt: ';
    if(code == 'irregular') return 'Änderung: ';
    return code ?? '';
  }

  static void show(BuildContext context, TimetableProps webuntisData, Appointment appointment) {
    (appointment.id as ArbitraryAppointment).handlers(
      (webuntis) => _webuntis(context, webuntisData, appointment, webuntis),
      (customData) => _custom(context, webuntisData, customData)
    );
  }

  static void _bottomSheet(
      BuildContext context,
      Widget Function(BuildContext context) header,
      SliverChildListDelegate Function(BuildContext context) body
  ) {
    showStickyFlexibleBottomSheet(
        minHeight: 0,
        initHeight: 0.4,
        maxHeight: 0.7,
        anchors: [0, 0.4, 0.7],
        isSafeArea: true,
        maxHeaderHeight: 100,

        context: context,
        headerBuilder: (context, bottomSheetOffset) => header(context),
        bodyBuilder: (context, bottomSheetOffset) => body(context)
    );
  }

  static void _webuntis(BuildContext context, TimetableProps webuntisData, Appointment appointment, GetTimetableResponseObject timetableData) {
    GetSubjectsResponseObject subject;
    GetRoomsResponseObject room;

    try {
      subject = webuntisData.getSubjectsResponse.result.firstWhere((subject) => subject.id == timetableData.su[0].id);
    } catch(e) {
      subject = GetSubjectsResponseObject(0, '?', 'Unbekannt', '?', true);
    }

    try {
      room = webuntisData.getRoomsResponse.result.firstWhere((room) => room.id == timetableData.ro[0].id);
    } catch(e) {
      room = GetRoomsResponseObject(0, '?', 'Unbekannt', true, '?');
    }

    _bottomSheet(
      context,
      (context) {
        return Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text("${_getEventPrefix(timetableData.code)}${subject.alternateName}", textAlign: TextAlign.center, style: const TextStyle(fontSize: 25), overflow: TextOverflow.ellipsis),
              Text(subject.longName),
              Text("${Jiffy.parseFromDateTime(appointment.startTime).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endTime).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)),
            ],
          ),
        );
      },

      (context) {
        return SliverChildListDelegate(
          [
            const Divider(),
            ListTile(
              leading: const Icon(Icons.notifications_active),
              title: Text("Status: ${timetableData.code != null ? "Geändert" : "Regulär"}"),
            ),
            ListTile(
              leading: const Icon(Icons.room),
              title: Text('Raum: ${room.name} (${room.longName})'),
              trailing: IconButton(
                icon: const Icon(Icons.house_outlined),
                onPressed: () {
                  pushScreen(context, withNavBar: false, screen: const Roomplan());
                },
              ),
            ),
            ListTile(
              leading: const Icon(Icons.person),
              title: timetableData.te.isNotEmpty
                  ? Text("Lehrkraft: ${timetableData.te[0].name} ${timetableData.te[0].longname.isNotEmpty ? "(${timetableData.te[0].longname})" : ""}")
                  : const Text('?'),
              trailing: Visibility(
                visible: !kReleaseMode,
                child: IconButton(
                  icon: const Icon(Icons.textsms_outlined),
                  onPressed: () {
                    UnimplementedDialog.show(context);
                  },
                ),
              ),
            ),
            ListTile(
              leading: const Icon(Icons.abc),
              title: Text('Typ: ${timetableData.activityType}'),
            ),
            ListTile(
              leading: const Icon(Icons.people),
              title: Text("Klasse(n): ${timetableData.kl.map((e) => e.name).join(", ")}"),
            ),
            DebugTile(context).jsonData(timetableData.toJson()),
          ],
        );
      }
    );
  }

  static Completer deleteCustomEvent(BuildContext context, CustomTimetableEvent appointment) {
    Completer future = Completer();
    ConfirmDialog(
      title: 'Termin löschen',
      content: "Der ${appointment.rrule.isEmpty ? "Termin" : "Serientermin"} wird unwiederruflich gelöscht.",
      confirmButton: 'Löschen',
      onConfirm: () {
        RemoveCustomTimetableEvent(
            RemoveCustomTimetableEventParams(
                appointment.id
            )
        ).run().then((value) {
          Provider.of<TimetableProps>(context, listen: false).run(renew: true);
          future.complete();
        });
      },
    ).asDialog(context);
    return future;
  }

  static void _custom(BuildContext context, TimetableProps webuntisData, CustomTimetableEvent appointment) {
    _bottomSheet(
      context,
      (context) {
        return Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(appointment.title, style: const TextStyle(fontSize: 25, overflow: TextOverflow.ellipsis)),
              Text("${Jiffy.parseFromDateTime(appointment.startDate).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endDate).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)),
            ],
          ),
        );
      },
      (context) {
        return SliverChildListDelegate(
          [
            const Divider(),
            Center(
              child: Wrap(
                children: [
                  TextButton.icon(
                    onPressed: () {
                      Navigator.of(context).pop();
                      showDialog(
                        context: context,
                        builder: (context) => CustomTimetableEventEditDialog(existingEvent: appointment),
                      );
                    },
                    label: const Text('Bearbeiten'),
                    icon: const Icon(Icons.edit_outlined),
                  ),
                  TextButton.icon(
                    onPressed: () {
                      deleteCustomEvent(context, appointment).future.then((value) => Navigator.of(context).pop());
                    },
                    label: const Text('Löschen'),
                    icon: const Icon(Icons.delete_outline),
                  ),
                ],
              ),
            ),
            const Divider(),
            ListTile(
              leading: const Icon(Icons.info_outline),
              title: Text(appointment.description.isEmpty ? 'Keine Beschreibung' : appointment.description),
            ),
            ListTile(
              leading: const CenteredLeading(Icon(Icons.repeat_outlined)),
              title: Text("Serie: ${appointment.rrule.isNotEmpty ? "Wiederholend" : "Einmailg"}"),
              subtitle: FutureBuilder(
                future: RruleL10nEn.create(),
                builder: (context, snapshot) {
                  if(appointment.rrule.isEmpty) return const Text('Keine weiteren vorkomnisse');
                  if(snapshot.data == null) return const Text('...');
                  RecurrenceRule rrule = RecurrenceRule.fromString(appointment.rrule);
                  if(!rrule.canFullyConvertToText) return const Text('Keine genauere Angabe möglich.');
                  return Text(rrule.toText(l10n: snapshot.data!));
                },
              )
            ),
            DebugTile(context).child(
              ListTile(
                leading: const CenteredLeading(Icon(Icons.rule)),
                title: const Text('RRule'),
                subtitle: Text(appointment.rrule.isEmpty ? 'Keine' : appointment.rrule),
              )
            ),
            DebugTile(context).jsonData(appointment.toJson()),
          ]
        );
      }
    );
  }
}