import 'dart:async';
import 'dart:ui' as ui;

import 'package:clarity_flutter/clarity_flutter.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/dental_chief_complaints_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/review_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/waiting_appointment/waiting_appointment_info.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';

class AppointmentCalendar extends StatefulWidget {
  AppointmentCalendar({super.key});

  @override
  State<AppointmentCalendar> createState() => _AppointmentCalendarState();
}

class _AppointmentCalendarState extends State<AppointmentCalendar> {
  late CalendarController _calendarController;

  late AppState appState;
  late BookAppointmentsViewModel bookAppointmentsViewModel;
  late AuthenticationViewModel authVM;

  var selectedDate = "";
  var selectedDateDisplay = "";
  var selectedNextDate = "";

  int selectedButtonIndex = 0;
  int selectedNextDayButtonIndex = -1;

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

  late Map<DateTime, List> _events;

  String selectedTime = "";

  final _selectedDay = DateTime.now();

  @override
  void initState() {
    Clarity.setCurrentScreenName('Select Doctor Free Slot Page');
    _calendarController = CalendarController();
    scheduleMicrotask(() {
      _events = {
        _selectedDay: ['Event A0']
      };
      _onDaySelected(DateUtil.convertStringToDate(bookAppointmentsViewModel.freeSlotsResponse[0]));
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
    authVM = Provider.of<AuthenticationViewModel>(context, listen: false);
    appState = getIt.get<AppState>();
    final isArabic = appState.isArabic();

    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 0.h),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // SizedBox(height: 24.h),
          // Row(
          //   crossAxisAlignment: CrossAxisAlignment.center,
          //   children: [
          //     "Pick a Date".toText20(isBold: true).expanded,
          //     Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() {
          //       Navigator.of(context).pop();
          //     }),
          //   ],
          // ),
          SizedBox(
            height: MediaQuery.of(context).size.height * 0.45,
            child: Stack(
              children: [
                Directionality(
                  textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr,
                  child: Localizations.override(
                    context: context,
                    locale: isArabic ? const Locale('ar', 'SA') : const Locale('en'),
                    child: ClarityUnmask(
                      child: SfCalendar(
                        controller: _calendarController,
                        minDate: DateTime.now(),
                        initialDisplayDate: DateUtil.convertStringToDate(bookAppointmentsViewModel.freeSlotsResponse[0]),
                        showNavigationArrow: false,
                        headerHeight: 60.h,
                        headerStyle: CalendarHeaderStyle(
                          backgroundColor: AppColors.transparent,
                          // textAlign: isArabic ? TextAlign.end : TextAlign.start,
                          textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor),
                        ),
                        viewHeaderStyle: ViewHeaderStyle(
                          // backgroundColor: AppColors.scaffoldBgColor,
                          dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor),
                        ),
                        view: CalendarView.month,
                        todayHighlightColor: Colors.transparent,
                        todayTextStyle: TextStyle(color: AppColors.textColor, fontWeight: FontWeight.bold),
                        selectionDecoration: ShapeDecoration(
                          color: AppColors.transparent,
                          shape: SmoothRectangleBorder(
                            borderRadius: BorderRadius.circular(10.r),
                            smoothness: 1,
                            side: BorderSide(color: AppColors.primaryRedColor, width: 1.5),
                          ),
                        ),
                        cellBorderColor: AppColors.transparent,
                        dataSource: MeetingDataSource(_getDataSource()),
                        monthCellBuilder: (context, details) => Padding(
                          padding: EdgeInsets.all(12.h),
                          child: details.date.day.toString().toText14(
                                isCenter: true,
                                color: details.date == _calendarController.selectedDate ? AppColors.primaryRedColor : AppColors.textColor,
                                isEnglishOnly: true,
                              ),
                        ),
                        monthViewSettings: MonthViewSettings(
                          dayFormat: "EEE",
                          appointmentDisplayMode: MonthAppointmentDisplayMode.indicator,
                          showTrailingAndLeadingDates: false,
                          appointmentDisplayCount: 1,
                          monthCellStyle: MonthCellStyle(
                            textStyle: TextStyle(fontSize: 19.f),
                          ),
                        ),
                        onTap: (CalendarTapDetails details) {
                          _calendarController.selectedDate = details.date;
                          _onDaySelected(details.date!);
                        },
                      ),
                    ),
                  ),
                ),
                // Custom Navigation Arrows
                Positioned(
                  top: 0,
                  right: isArabic ? null : 0,
                  left: isArabic ? 0 : null,
                  child: SizedBox(
                    height: 60.h,
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        // Previous Month Arrow
                        GestureDetector(
                          onTap: () {
                            setState(() {
                              _calendarController.backward!();
                            });
                          },
                          child: Container(
                            padding: EdgeInsets.all(8.h),
                            child: Icon(
                              // isArabic ? Icons.arrow_forward_ios : Icons.arrow_back_ios,
                              Icons.arrow_back_ios,
                              size: 24.h,
                              color: AppColors.primaryRedColor,
                            ),
                          ),
                        ),
                        // Next Month Arrow
                        GestureDetector(
                          onTap: () {
                            setState(() {
                              _calendarController.forward!();
                            });
                          },
                          child: Container(
                            padding: EdgeInsets.all(8.h),
                            child: Icon(
                              // isArabic ? Icons.arrow_back_ios : Icons.arrow_forward_ios,
                              Icons.arrow_forward_ios,
                              size: 24.h,
                              color: AppColors.primaryRedColor,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          SizedBox(height: 10.h),
          Transform.translate(
            offset: const Offset(0.0, -10.0),
            child: ClarityUnmask(child: selectedDateDisplay.toText16(isBold: true, isEnglishOnly: !isArabic)),
          ),
          //TODO: Add Next Day Span here
          dayEvents.isNotEmpty
              ? ClarityUnmask(
                  child: ConstrainedBox(
                    constraints: BoxConstraints(
                      maxHeight: MediaQuery.of(context).size.height * 0.25,
                      minHeight: 0,
                    ),
                    child: Directionality(
                      textDirection: isArabic ? ui.TextDirection.rtl : ui.TextDirection.ltr,
                      child: SingleChildScrollView(
                        scrollDirection: Axis.vertical,
                        child: Wrap(
                          direction: Axis.horizontal,
                          alignment: WrapAlignment.start,
                          spacing: 6.h,
                          runSpacing: 6.h,
                          children: List.generate(
                            dayEvents.length,
                            (index) => TimeSlotChip(
                              label: dayEvents[index].isoTime!,
                              isSelected: index == selectedButtonIndex,
                              onTap: () {
                                setState(() {
                                  selectedButtonIndex = index;
                                  selectedTime = dayEvents[index].isoTime!;
                                });
                              },
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                )
              : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noFreeSlot.tr(context: context)),

          SizedBox(height: 16.h),
          CustomButton(
            text: LocaleKeys.selectDateTimeKey.tr(context: context),
            isDisabled: dayEvents.isEmpty,
            onPressed: () async {
              if (appState.isAuthenticated) {
                if (selectedTime == LocaleKeys.waitingAppointment.tr(context: context)) {
                  bookAppointmentsViewModel.setWaitingAppointmentProjectID(bookAppointmentsViewModel.selectedDoctor.projectID!);
                  bookAppointmentsViewModel.setWaitingAppointmentDoctor(bookAppointmentsViewModel.selectedDoctor);

                  Navigator.of(context).pop();
                  Navigator.of(context).push(
                    CustomPageRoute(
                      page: WaitingAppointmentInfo(),
                    ),
                  );
                } else {
                  if (bookAppointmentsViewModel.selectedClinic.clinicID == 17 && bookAppointmentsViewModel.selectedChiefComplaintID == 0) {
                    GetClinicsListResponseModel selectedClinic = GetClinicsListResponseModel(
                        clinicID: bookAppointmentsViewModel.selectedClinic.clinicID,
                        clinicDescription: bookAppointmentsViewModel.selectedClinic.clinicDescription,
                        isLiveCareClinicAndOnline: false,
                        liveCareServiceID: 0,
                        liveCareClinicID: 0);
                    bookAppointmentsViewModel.setProjectID(bookAppointmentsViewModel.selectedDoctor.projectID.toString());
                    bookAppointmentsViewModel.setSelectedClinic(selectedClinic);
                    bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true);
                    Navigator.of(context).push(
                      CustomPageRoute(
                        page: DentalChiefComplaintsPage(),
                      ),
                    );
                  } else {
                    bookAppointmentsViewModel.getAppointmentNearestGate(projectID: bookAppointmentsViewModel.selectedDoctor.projectID!, clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID!);
                    bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime, selectedDateDisplay);
                    Navigator.of(context).pop();
                    Navigator.of(context).push(
                      CustomPageRoute(
                        page: ReviewAppointmentPage(),
                      ),
                    );
                  }
                }
              } else {
                showCommonBottomSheetWithoutHeight(
                  context,
                  title: LocaleKeys.notice.tr(context: context),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
                      SizedBox(height: 8.h),
                      (LocaleKeys.loginToUseService.tr(context: context)).toText16(color: AppColors.blackColor),
                      SizedBox(height: 16.h),
                      Row(
                        children: [
                          Expanded(
                            child: CustomButton(
                              text: LocaleKeys.cancel.tr(context: context),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                              backgroundColor: AppColors.secondaryLightRedColor,
                              borderColor: AppColors.secondaryLightRedColor,
                              textColor: AppColors.primaryRedColor,
                              icon: AppAssets.cancel,
                              iconColor: AppColors.primaryRedColor,
                            ),
                          ),
                          SizedBox(width: 8.h),
                          Expanded(
                            child: CustomButton(
                              text: LocaleKeys.confirm.tr(context: context),
                              onPressed: () async {
                                Navigator.of(context).pop();
                                Navigator.pushAndRemoveUntil(
                                    context,
                                    CustomPageRoute(
                                      page: LandingNavigation(),
                                    ),
                                    (r) => false);
                                await authVM.onLoginPressed();
                                // Navigator.of(context).push(
                                //   FadePage(page: MyAppointmentsPage()),
                                // );
                              },
                              backgroundColor: AppColors.bgGreenColor,
                              borderColor: AppColors.bgGreenColor,
                              textColor: Colors.white,
                              icon: AppAssets.confirm,
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 16.h),
                    ],
                  ).center,
                  callBackFunc: () {},
                  isFullScreen: false,
                  isCloseButtonVisible: true,
                );
              }
            },
            backgroundColor: AppColors.primaryRedColor,
            borderColor: AppColors.primaryRedColor,
            textColor: Colors.white,
            fontSize: 16.f,
            isBold: true,
            borderRadius: 10.r,
            padding: EdgeInsets.symmetric(horizontal: 10.w),
            height: 50.h,
          ),
        ],
      ),
    );
  }

  List<Meeting> _getDataSource() {
    final List<Meeting> meetings = <Meeting>[];
    for (var slot in bookAppointmentsViewModel.freeSlotsResponse) {
      final startTime = DateUtil.convertStringToDate(slot);

      final endTime = startTime.add(const Duration(minutes: 15));

      meetings.add(Meeting(
          "Available", // Or leave empty with ""
          startTime,
          endTime,
          AppColors.primaryRedColor,
          false,
          "" // Optional notes
          ));
    }
    return meetings;
  }

  // TODO:
  openTimeSlotsPickerForDate(DateTime dateStart, List<TimeSlot> freeSlots) {
    dayEvents.clear();
    DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0);
    if (bookAppointmentsViewModel.isWaitingAppointmentAvailable && DateUtils.isSameDay(dateStart, DateTime.now())) {
      dayEvents.add(TimeSlot(isoTime: LocaleKeys.waitingAppointment.tr(context: context), start: DateTime.now(), end: DateTime.now(), vidaDate: ""));
    }
    for (var v in freeSlots) {
      if (v.start == dateStartObj) dayEvents.add(v);
    }
    selectedButtonIndex = 0;
    List<Map<String, dynamic>> timeList = [];
    for (var i = 0; i < dayEvents.length; i++) {
      Map<String, dynamic> timeSlot = {"isoTime": dayEvents[i].isoTime, "start": dayEvents[i].start.toString(), "end": dayEvents[i].end.toString(), "vidaDate": dayEvents[i].vidaDate};
      timeList.add(timeSlot);
    }
    if (dayEvents.isNotEmpty) {
      selectedTime = dayEvents[selectedButtonIndex].isoTime!;
    }
    setState(() {});
  }

  void _onDaySelected(DateTime day) {
    final DateFormat formatter = DateFormat('yyyy-MM-dd', "en-US");
    final isArabic = appState.isArabic();
    setState(() {
      selectedDateDisplay = isArabic ? DateUtil.getMonthDayYearDateFormattedAr(day) : DateUtil.getMonthDayYearDateFormatted(day);
      selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), isArabic ? "ar" : "en");
      _calendarController.selectedDate = day;
      openTimeSlotsPickerForDate(day, bookAppointmentsViewModel.docFreeSlots);
      selectedDate = formatter.format(day);
      selectedNextDayButtonIndex = -1;
      print(_calendarController.selectedDate);
    });
  }
}

class TimeSlotChip extends StatelessWidget {
  final String label;
  final bool isSelected;
  final VoidCallback? onTap;

  const TimeSlotChip({super.key, required this.label, this.isSelected = false, this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: label == LocaleKeys.waitingAppointment.tr(context: context)
          ? Container(
              padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h),
              decoration: ShapeDecoration(
                color: isSelected ? AppColors.warningColorYellow : AppColors.whiteColor,
                shape: SmoothRectangleBorder(
                  borderRadius: BorderRadius.circular(8.h),
                  smoothness: 1,
                  side: BorderSide(color: isSelected ? AppColors.warningColorYellow : AppColors.borderOnlyColor.withOpacity(0.2), width: 1),
                ),
              ),
              child: label.toText12(color: isSelected ? AppColors.whiteColor : Colors.black87, isBold: true, isEnglishOnly: true),
            )
          : Container(
              padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h),
              decoration: ShapeDecoration(
                color: AppColors.whiteColor,
                shape: SmoothRectangleBorder(
                  borderRadius: BorderRadius.circular(8.h),
                  smoothness: 1,
                  side: BorderSide(color: isSelected ? AppColors.primaryRedColor : AppColors.borderOnlyColor.withOpacity(0.2), width: 1),
                ),
              ),
              child: label.toText12(color: isSelected ? AppColors.primaryRedColor : AppColors.textColor, isBold: true, isEnglishOnly: true),
            ),
    );
  }
}

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;
}
