import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
import 'package:hmg_patient_app/models/Appointments/AppoimentAllHistoryResultList.dart';
import 'package:hmg_patient_app/models/Appointments/DoctorListResponse.dart';
import 'package:hmg_patient_app/models/Appointments/FreeSlot.dart';
import 'package:hmg_patient_app/models/Appointments/OBGyneProcedureListResponse.dart';
import 'package:hmg_patient_app/models/Appointments/timeSlot.dart';
import 'package:hmg_patient_app/models/Appointments/toDoCountProviderModel.dart';
import 'package:hmg_patient_app/pages/landing/landing_page.dart';
import 'package:hmg_patient_app/services/appointment_services/GetDoctorsList.dart';
import 'package:hmg_patient_app/services/clinic_services/get_clinic_service.dart';
import 'package:hmg_patient_app/theme/colors.dart';
import 'package:hmg_patient_app/uitl/app_shared_preferences.dart';
import 'package:hmg_patient_app/uitl/app_toast.dart';
import 'package:hmg_patient_app/uitl/date_uitl.dart';
import 'package:hmg_patient_app/uitl/gif_loader_dialog_utils.dart';
import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
import 'package:hmg_patient_app/uitl/utils_new.dart';
import 'package:hmg_patient_app/widgets/buttons/custom_text_button.dart';
import 'package:hmg_patient_app/widgets/dialogs/confirm_dialog.dart';
import 'package:hmg_patient_app/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';

class ObGyneTimeSlots extends StatefulWidget {
  int projectID;
  static bool areSlotsAvailable = false;
  static late DateTime selectedAppoDateTime;
  static late String selectedDate;
  static late String selectedTime;

  late int? selectedClinicID;
  late int? selectedDoctorID;

  late OBGyneProcedureListResponse? obGyneProcedureListResponse;

  var language;

  ObGyneTimeSlots({required this.projectID, this.selectedClinicID, this.selectedDoctorID, this.obGyneProcedureListResponse});

  @override
  _CovidTimeSlotsState createState() => _CovidTimeSlotsState();
}

class _CovidTimeSlotsState extends State<ObGyneTimeSlots> with TickerProviderStateMixin {
  Map<DateTime, List>? _events;
  AnimationController? _animationController;
  CalendarController? _calendarController;

  AppSharedPreferences sharedPref = new AppSharedPreferences();

  var selectedDate = "";
  dynamic selectedDateJSON;
  dynamic jsonFreeSlots;

  List<TimeSlot> docFreeSlots = [];
  List<TimeSlot> dayEvents = [];

  int selectedButtonIndex = 0;

  dynamic freeSlotsResponse;

  ScrollController? _scrollController;

  ToDoCountProviderModel? toDoProvider;
  ProjectViewModel? projectViewModel;

  @override
  void initState() {
    final _selectedDay = DateTime.now();

    _scrollController = new ScrollController();

    _events = {
      _selectedDay: ['Event A0']
    };

    WidgetsBinding.instance.addPostFrameCallback((_) => getCovidFreeSlots(context, widget.projectID));

    _calendarController = CalendarController();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 50),
    );

    _animationController!.forward();
    super.initState();
  }

  @override
  void dispose() {
    _animationController!.dispose();
    _calendarController!.dispose();
    super.dispose();
  }

  void _onDaySelected(DateTime day, ProjectViewModel projectViewModel) {
    final DateFormat formatter = DateFormat('yyyy-MM-dd');
    setState(() {
      this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, projectViewModel.isArabic ? "ar" : "en");
      openTimeSlotsPickerForDate(day, docFreeSlots);
      ObGyneTimeSlots.selectedDate = formatter.format(day);
      _calendarController!.selectedDate = day;
      print(ObGyneTimeSlots.selectedDate);
    });
  }

  @override
  Widget build(BuildContext context) {
    projectViewModel = Provider.of(context);
    toDoProvider = Provider.of<ToDoCountProviderModel>(context);
    return AppScaffold(
      appBarTitle: TranslationBase.of(context).bookAppo,
      isShowAppBar: true,
      showNewAppBar: true,
      showNewAppBarTitle: true,
      backgroundColor: CustomColors.appBackgroudGrey2Color,
      body: Column(
        children: [
          Expanded(
            child: SingleChildScrollView(
              child: Container(
                margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Container(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisSize: MainAxisSize.max,
                        children: <Widget>[
                          Text(
                            TranslationBase.of(context).selectAppo,
                            style: TextStyle(
                              color: Colors.black,
                              fontSize: 16.0,
                              letterSpacing: -0.64,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                          mHeight(12),
                          Container(
                            decoration: cardRadius(12),
                            child: _buildTableCalendarWithBuilders(projectViewModel!),
                          ),
                          mHeight(12),
                          Text(
                            selectedDate,
                            style: TextStyle(
                              fontSize: 16.0,
                              fontWeight: FontWeight.bold,
                              letterSpacing: -0.64,
                            ),
                          ),
                          mHeight(8),
                          ObGyneTimeSlots.areSlotsAvailable
                              ? Container(
                                  height: 40,
                                  child: ListView.builder(
                                    controller: _scrollController,
                                    scrollDirection: Axis.horizontal,
                                    itemCount: dayEvents.length,
                                    itemBuilder: (context, index) {
                                      return Container(
                                        margin: EdgeInsets.only(right: (index == dayEvents.length - 1) ? 0 : 5.0, left: index == 0 ? 0 : 5),
                                        child: ButtonTheme(
                                            shape: RoundedRectangleBorder(
                                              borderRadius: BorderRadius.circular(5.0),
                                              side: BorderSide(
                                                color: index == selectedButtonIndex ? CustomColors.green : Colors.black, //Color of the border
                                                style: BorderStyle.solid, //Style of the border
                                                width: 1.5, //width of the border
                                              ),
                                            ),
                                            minWidth: MediaQuery.of(context).size.width * 0.2,
                                            child: index == selectedButtonIndex ? getSelectedButton(index) : getNormalButton(index)),
                                      );
                                    },
                                  ),
                                )
                              : Center(
                                  child: Padding(
                                  padding: const EdgeInsets.only(left: 12.0, right: 12.0),
                                  child: Text(TranslationBase.of(context).noSlotsError, style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: CustomColors.grey)),
                                )),
                        ],
                      ),
                    ),
                    SizedBox(
                      height: 100.0,
                    ),
                  ],
                ),
              ),
            ),
          ),
          Container(
            margin: EdgeInsets.zero,
            decoration: cardRadius(0),
            child: Container(
              width: double.infinity,
              padding: EdgeInsets.all(12),
              child: ButtonTheme(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10.0),
                ),
                minWidth: MediaQuery.of(context).size.width * 0.7,
                height: 45.0,
                child: CustomTextButton(
                  backgroundColor: CustomColors.green,
                  disabledForegroundColor: Colors.grey[500]!.withOpacity(0.38),
                  disabledBackgroundColor: Colors.grey[500]!.withOpacity(0.12),
                  elevation: 0,
                  onPressed: () {
                    bookCovidTestAppointment();
                  },
                  child: Text(
                    TranslationBase.of(context).bookAppo,
                    style: TextStyle(fontSize: 16.0, letterSpacing: -0.64, color: Colors.white),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  Widget _buildTableCalendarWithBuilders(ProjectViewModel projectViewModel) {
    return SfCalendar(
      controller: _calendarController,
      minDate: DateTime.now(),
      showNavigationArrow: true,
      headerStyle: CalendarHeaderStyle(textAlign: TextAlign.center, textStyle: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.46)),
      viewHeaderStyle: ViewHeaderStyle(dayTextStyle: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: CustomColors.black)),
      view: CalendarView.month,
      todayHighlightColor: CustomColors.green,
      selectionDecoration: containerColorRadiusBorderWidthCircular(Colors.transparent, 4, CustomColors.green, 2.5),
      cellBorderColor: Colors.white,
      dataSource: MeetingDataSource(_getDataSource()),
      monthViewSettings: const MonthViewSettings(appointmentDisplayMode: MonthAppointmentDisplayMode.indicator, showTrailingAndLeadingDates: false, appointmentDisplayCount: 1),
      onTap: (CalendarTapDetails details) {
        _calendarController!.selectedDate = details.date;
        _onDaySelected(details.date!, projectViewModel);
      },
    );
  }

  List<Meeting> _getDataSource() {
    final List<Meeting> meetings = <Meeting>[];
    _events!.forEach((key, value) {
      final DateTime startTime = DateTime(key.year, key.month, key.day, 9, 0, 0);
      final DateTime endTime = startTime.add(const Duration(minutes: 20));
      meetings.add(Meeting("", startTime, endTime, CustomColors.green, false, ""));
    });
    return meetings;
  }

  openTimeSlotsPickerForDate(DateTime dateStart, List<TimeSlot> freeSlots) {
    dayEvents.clear();
    DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0);

    freeSlots.forEach((v) {
      if (v.start == dateStartObj) dayEvents.add(v);
    });

    setState(() {
      if (dayEvents.length != 0) {
        ObGyneTimeSlots.areSlotsAvailable = true;
        selectedButtonIndex = 0;
        ObGyneTimeSlots.selectedTime = dayEvents![selectedButtonIndex]!.isoTime!;
      } else
        ObGyneTimeSlots.areSlotsAvailable = false;
    });
  }

  Future<Map<DateTime, List>> _getJSONSlots() async {
    Map<DateTime, List> _eventsParsed;
    List<FreeSlot> slotsList = [];
    DateTime date;
    final DateFormat formatter = DateFormat('HH:mm');
    final DateFormat dateFormatter = DateFormat('yyyy-MM-dd');
    for (var i = 0; i < freeSlotsResponse.length; i++) {
      date = DateUtil.convertStringToDate(freeSlotsResponse[i]);
      slotsList.add(FreeSlot(date, ['slot']));
      docFreeSlots.add(TimeSlot(isoTime: formatter.format(date), start: new DateTime(date.year, date.month, date.day, 0, 0, 0, 0), end: date));
    }
    _eventsParsed = Map.fromIterable(slotsList, key: (e) => e.slot, value: (e) => e.event);
    setState(() {
      ObGyneTimeSlots.selectedDate = dateFormatter.format(DateUtil.convertStringToDate(freeSlotsResponse[0]));
      selectedDate = DateUtil.getMonthDayYearDateFormatted(DateUtil.convertStringToDate(freeSlotsResponse[0]));
      selectedDateJSON = freeSlotsResponse[0];
    });
    openTimeSlotsPickerForDate(DateUtil.convertStringToDate(selectedDateJSON), docFreeSlots);
    _calendarController!.selectedDate = DateUtil.convertStringToDate(selectedDateJSON);
    return _eventsParsed;
  }

  Widget getNormalButton(int index) {
    return CustomTextButton(
      backgroundColor: Colors.white,
      elevation: 0,
      onPressed: () {
        setState(() {
          selectedButtonIndex = index;
          ObGyneTimeSlots.selectedTime = dayEvents[index].isoTime!;
          print(ObGyneTimeSlots.selectedTime);
        });
      },
      child: Text(dayEvents[index].isoTime!, style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold, color: Color(0xFF60686b))),
    );
  }

  Widget getSelectedButton(int index) {
    return CustomTextButton(
      backgroundColor: CustomColors.green,
      elevation: 0,
      onPressed: () {
        setState(() {
          selectedButtonIndex = index;
          ObGyneTimeSlots.selectedTime = dayEvents[index].isoTime!;
          print(ObGyneTimeSlots.selectedTime);
        });
      },
      child: Text(dayEvents[index].isoTime!, style: TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold, color: Colors.white)),
    );
  }

  bookCovidTestAppointment() {
    if (ObGyneTimeSlots.areSlotsAvailable) {
      GifLoaderDialogUtils.showMyDialog(context);
      DoctorList docObject = new DoctorList();
      docObject.doctorID = widget.selectedDoctorID;
      docObject.clinicID = widget.selectedClinicID;
      docObject.projectID = widget.projectID;
      insertAppointmentCovidTest(context, docObject);
    } else {
      AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot);
    }
  }

  // updateCovidQuestionnaire(context, String appoNo) async {
  //   DoctorsListService service = new DoctorsListService();
  //   service.updateCovidQuestionnaire(appoNo, widget.projectID, widget.selectedProject.testTypeEnum, widget.selectedProject.testProcedureEnum).then((res) {}).catchError((err) {
  //     print(err);
  //   });
  // }

  insertAppointmentCovidTest(context, DoctorList docObject) {
    DoctorsListService service = new DoctorsListService();
    AppoitmentAllHistoryResultList appo;
    service
        .insertAppointment(docObject.doctorID!, docObject.clinicID!, docObject.projectID!, ObGyneTimeSlots.selectedTime, ObGyneTimeSlots.selectedDate, 0, projectViewModel!.isArabic ? 1 : 2, context,
            widget.obGyneProcedureListResponse!.procedureId)
        .then((res) {
      if (res['MessageStatus'] == 1) {
        AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess);
        updateObGyneAppointment(res['AppointmentNo']);
        getToDoCount();
        // getPatientShare(context, res['AppointmentNo'], docObject.clinicID, docObject.projectID, docObject);
      } else {
        GifLoaderDialogUtils.hideDialog(context);
        appo = new AppoitmentAllHistoryResultList();
        appo.appointmentNo = res['SameClinicApptList'][0]['AppointmentNo'];
        appo.clinicID = res['SameClinicApptList'][0]['DoctorID'];
        appo.projectID = res['SameClinicApptList'][0]['ProjectID'];
        appo.endTime = res['SameClinicApptList'][0]['EndTime'];
        appo.startTime = res['SameClinicApptList'][0]['StartTime'];
        appo.doctorID = res['SameClinicApptList'][0]['DoctorID'];
        appo.isLiveCareAppointment = false;
        appo.originalClinicID = 0;
        appo.originalProjectID = 0;
        appo.appointmentDate = res['SameClinicApptList'][0]['AppointmentDate'];

        ConfirmDialog dialog = new ConfirmDialog(
            context: context,
            confirmMessage: res['ErrorEndUserMessage'],
            okText: TranslationBase.of(context).confirm,
            cancelText: TranslationBase.of(context).cancel_nocaps,
            okFunction: () => {cancelAppointment(docObject, appo, context)},
            cancelFunction: () => {});
        dialog.showAlertDialog(context);
      }
    }).catchError((err) {
      AppToast.showErrorToast(message: err);
      GifLoaderDialogUtils.hideDialog(context);
      print(err);
    });
  }

  updateObGyneAppointment(String appoNo) {
    DoctorsListService service = new DoctorsListService();
    service
        .updateObGyneAppointment(widget.obGyneProcedureListResponse!.episodeID!, int.parse(appoNo), widget.obGyneProcedureListResponse!.orderNo!, widget.obGyneProcedureListResponse!.procedureId!,
            widget.obGyneProcedureListResponse!.lineItemNo!, widget.obGyneProcedureListResponse!.uniqueRowID!, projectViewModel!.isArabic ? 1 : 2)
        .then((res) {})
        .catchError((err) {
      print(err);
    });
  }

  getToDoCount() {
    toDoProvider!.setState(0, 0, true, toDoProvider!.notificationsCount);
    ClinicListService service = new ClinicListService();
    service.getActiveAppointmentNo(context).then((res) {
      GifLoaderDialogUtils.hideDialog(context);
      print(res['AppointmentActiveNumber']);
      if (res['MessageStatus'] == 1) {
        // toDoProvider.setState(res['AppointmentActiveNumber'], true, toDoProvider.notificationsCount);
        toDoProvider!.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, toDoProvider!.notificationsCount);
      } else {}
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (context) => LandingPage()),
        (Route<dynamic> route) => false,
      );
    }).catchError((err) {
      GifLoaderDialogUtils.hideDialog(context);
      print(err);
    });
  }

  cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context) {
    ConfirmDialog.closeAlertDialog(context);
    GifLoaderDialogUtils.showMyDialog(context);
    DoctorsListService service = new DoctorsListService();
    service.cancelAppointment(appo, context).then((res) {
      if (res['MessageStatus'] == 1) {
        // Future.delayed(new Duration(milliseconds: 1500), () {
        insertAppointmentCovidTest(context, docObject);
        // });
      } else {
        GifLoaderDialogUtils.hideDialog(context);
        AppToast.showErrorToast(message: res['ErrorEndUserMessage']);
      }
    }).catchError((err) {
      print(err);
    });
  }

  // getPatientShare(context, String appointmentNo, int clinicID, int projectID, DoctorList docObject) {
  //   DoctorsListService service = new DoctorsListService();
  //   service.getPatientShare(appointmentNo, clinicID, projectID, context).then((res) {
  //     GifLoaderDialogUtils.hideDialog(context);
  //     print(res);
  //     widget.patientShareResponse = new PatientShareResponse.fromJson(res);
  //     // updateCovidQuestionnaire(context, appointmentNo);
  //     navigateToPaymentAlert();
  //   }).catchError((err) {
  //     GifLoaderDialogUtils.hideDialog(context);
  //     print(err);
  //   });
  // }
  //
  // navigateToPaymentAlert() {
  //   Navigator.push(
  //     context,
  //     FadePage(
  //       page: CovidPaymentAlert(patientShareResponse: widget.patientShareResponse),
  //     ),
  //   );
  // }

  getCovidFreeSlots(BuildContext context, int projectID) {
    DoctorsListService service = new DoctorsListService();
    GifLoaderDialogUtils.showMyDialog(context);
    service.getDoctorFreeSlots(widget.selectedDoctorID!, widget.selectedClinicID!, widget.projectID, false, context).then((res) {
      GifLoaderDialogUtils.hideDialog(context);
      if (res['MessageStatus'] == 1) {
        if (res['FreeTimeSlots'].length != 0) {
          print(res['FreeTimeSlots']);
          freeSlotsResponse = res['FreeTimeSlots'];
          _getJSONSlots().then((value) => {
                setState(() => {
                      _events!.clear(),
                      _events = value,
                      // if (widget.doctorSchedule != null)
                      //   {_onDaySelected(DateUtil.convertStringToDate(widget.doctorSchedule['Date'])), _calendarController.selectedDate = DateUtil.convertStringToDate(widget.doctorSchedule['Date'])}
                    })
              });
        } else {}
      } else {
        GifLoaderDialogUtils.hideDialog(context);
        AppToast.showErrorToast(message: res['ErrorEndUserMessage']);
      }
    }).catchError((err) {
      GifLoaderDialogUtils.hideDialog(context);
      AppToast.showErrorToast(message: err.toString());
      print(err);
    });
  }
}

class MeetingDataSource extends CalendarDataSource {
  MeetingDataSource(List<Meeting> source) {
    appointments = source;
  }

  @override
  DateTime getStartTime(int index) {
    return _getMeetingData(index)!.from!;
  }

  @override
  DateTime getEndTime(int index) {
    return _getMeetingData(index)!.to!;
  }

  @override
  String getSubject(int index) {
    return _getMeetingData(index)!.eventName;
  }

  @override
  Color getColor(int index) {
    return _getMeetingData(index)!.background;
  }

  @override
  bool isAllDay(int index) {
    return _getMeetingData(index)!.isAllDay;
  }

  Meeting? _getMeetingData(int index) {
    final dynamic meeting = appointments![index];
    Meeting? meetingData;
    if (meeting is Meeting) {
      meetingData = meeting;
    }
    return meetingData!;
  }
}

class Meeting {
  Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, this.notes);

  String eventName;
  DateTime from;
  DateTime to;
  Color background;
  bool isAllDay;
  String notes;
}
