import 'dart:async';

import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.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/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/timeslots.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/review_appointment_page.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:hmg_patient_app_new/widgets/transitions/fade_page.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 {
  const 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 = "";

  bool isWaitingAppointmentAvailable = false;
  final _selectedDay = DateTime.now();

  @override
  void initState() {
    scheduleMicrotask(() {
      _calendarController = CalendarController();
      _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>();
    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(weight: FontWeight.w600).expanded,
          //     Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() {
          //       Navigator.of(context).pop();
          //     }),
          //   ],
          // ),
          SizedBox(
            height: 350.h,
            child: SfCalendar(
              controller: _calendarController,
              minDate: DateTime.now(),
              showNavigationArrow: true,
              headerHeight: 60.h,
              headerStyle: CalendarHeaderStyle(
                backgroundColor: AppColors.scaffoldBgColor,
                textAlign: TextAlign.start,
                textStyle: TextStyle(fontSize: 18.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
              ),
              viewHeaderStyle: ViewHeaderStyle(
                backgroundColor: AppColors.scaffoldBgColor,
                dayTextStyle: TextStyle(fontSize: 14.fSize, 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(12 ?? 0),
                  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,
                    ),
              ),
              monthViewSettings: MonthViewSettings(
                dayFormat: "EEE",
                appointmentDisplayMode: MonthAppointmentDisplayMode.indicator,
                showTrailingAndLeadingDates: false,
                appointmentDisplayCount: 1,
                monthCellStyle: MonthCellStyle(
                  textStyle: TextStyle(fontSize: 19.fSize),
                ),
              ),
              onTap: (CalendarTapDetails details) {
                _calendarController.selectedDate = details.date;
                _onDaySelected(details.date!);
              },
            ),
          ),
          Transform.translate(
            offset: const Offset(0.0, -20.0),
            child: selectedDateDisplay.toText16(weight: FontWeight.w500),
          ),
          //TODO: Add Next Day Span here
          SizedBox(
            height: 100.h,
            child: SingleChildScrollView(
              scrollDirection: Axis.vertical,
              child: Wrap(
                direction: Axis.horizontal,
                alignment: WrapAlignment.start,
                spacing: 6.h,
                runSpacing: 6.h,
                children: List.generate(
                  dayEvents.length, // Generate a large number of items to ensure scrolling
                  (index) => TimeSlotChip(
                    label: dayEvents[index].isoTime!,
                    isSelected: index == selectedButtonIndex,
                    onTap: () {
                      setState(() {
                        selectedButtonIndex = index;
                        selectedTime = dayEvents[index].isoTime!;
                      });
                    },
                  ),
                ),
              ),
            ),
          ),
          SizedBox(height: 16.h),
          CustomButton(
            text: "Select".needTranslation,
            onPressed: () async {
              if (appState.isAuthenticated) {
                bookAppointmentsViewModel.setSelectedAppointmentDateTime(selectedDate, selectedTime);
                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()).toText16(color: AppColors.blackColor),
                      SizedBox(height: 16.h),
                      Row(
                        children: [
                          Expanded(
                            child: CustomButton(
                              text: LocaleKeys.cancel.tr(),
                              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(),
                              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: AppColors.whiteColor,
            fontSize: 16,
            fontWeight: FontWeight.w500,
            borderRadius: 12,
            padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
            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 (isWaitingAppointmentAvailable && DateUtils.isSameDay(dateStart, DateTime.now())) {
      dayEvents.add(TimeSlot(isoTime: "Waiting Appointment", start: DateTime.now(), end: DateTime.now(), vidaDate: ""));
    }
    freeSlots.forEach((v) {
      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);
    }
    selectedTime = dayEvents[selectedButtonIndex].isoTime!;
  }

  void _onDaySelected(DateTime day) {
    final DateFormat formatter = DateFormat('yyyy-MM-dd');
    setState(() {
      selectedDateDisplay = DateUtil.getMonthDayYearDateFormatted(day);
      selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), "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: 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 : Colors.black87,
          fontWeight: FontWeight.w500,
        ),
      ),
    );
  }
}

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