import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import 'package:table_calendar/table_calendar.dart';

class CustomCalenderAppointmentWidget extends StatefulWidget {
  final List<CustomTimeDateSlotModel> customTimeDateSlotList;
  final CustomTimeDateSlotModel? selectedCustomTimeDateSlotModel;
  final Function(int) onDateSelected;

  const CustomCalenderAppointmentWidget({
    super.key,
    required this.customTimeDateSlotList,
    required this.selectedCustomTimeDateSlotModel,
    required this.onDateSelected,
  });

  @override
  State<CustomCalenderAppointmentWidget> createState() => _CustomCalenderAppointmentWidgetState();
}

class _CustomCalenderAppointmentWidgetState extends State<CustomCalenderAppointmentWidget> {
  List<DateTime> allDates = [];
  List<DropValue> allMonths = [];
  List<DateTime> datesInSelectedMonth = [];
  final CalendarFormat _calendarFormat = CalendarFormat.month;

  late int selectedMonth;
  late int selectedYear;

  DateTime? _selectedDay;

  DateTime _focusedDay = DateTime.now();

  @override
  void initState() {
    super.initState();
    populateDateList();
  }

  populateDateList() {
    for (var value in widget.customTimeDateSlotList) {
      DateTime dt = DateFormat('dd MMMM, yyyy').parse(value.date!.date.trim());
      DropValue dv = DropValue(dt.month, "${dt.month.getMonthNameByNumber()}, ${dt.year}", "${dt.year}");
      allDates.add(dt);

      if (!ifMonthAlreadyThere(dv)) {
        allMonths.add(dv);
      }
    }
    selectedMonth = allDates.first.month;
    selectedYear = allDates.first.year;
    if (widget.selectedCustomTimeDateSlotModel != null) {
      DateTime alreadySelectedDate = DateFormat('dd MMMM, yyyy').parse(widget.selectedCustomTimeDateSlotModel!.date!.date);
      _selectedDay = alreadySelectedDate;
      _focusedDay = alreadySelectedDate;
      selectedMonth = alreadySelectedDate.month;
      selectedYear = alreadySelectedDate.year;
    }
    datesInSelectedMonth = allDates.where((element) => element.month == selectedMonth).toList();

    if (widget.selectedCustomTimeDateSlotModel == null) {
      _focusedDay = datesInSelectedMonth.first;
    }
  }

  bool ifMonthAlreadyThere(DropValue monthDate) {
    int index = allMonths.indexWhere((element) => element.id == monthDate.id && element.subValue == monthDate.subValue);
    if (index == -1) {
      return false;
    }
    return true;
  }

  bool ifDateAlreadyThere(DateTime dt) {
    int index = allDates.indexWhere((element) => dt.month == element.month && dt.year == element.year);
    if (index == -1) {
      return false;
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
        return Column(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Expanded(
                  child: Builder(builder: (context) {
                    return DropdownField(
                      (DropValue value) {
                        setState(() {
                          selectedYear = int.parse(value.value.split(',')[1]);
                          selectedMonth = value.value.split(',')[0].getMonthNumberByName();
                          datesInSelectedMonth = allDates.where((element) => element.month == selectedMonth).toList();
                          _focusedDay = datesInSelectedMonth.first;
                        });
                      },
                      list: allMonths,
                      dropdownValue: DropValue(selectedMonth, "${selectedMonth.getMonthNameByNumber()}, $selectedYear", "$selectedYear"),
                      hint: "${selectedMonth.getMonthNameByNumber()}, $selectedYear",
                      errorValue: "",
                      showAppointmentPickerVariant: true,
                    );
                  }),
                ),
                const Spacer(),
                const Icon(
                  Icons.calendar_today,
                  color: Colors.black,
                  size: 18,
                ).paddingOnly(right: 10)
              ],
            ).paddingOnly(left: 6, right: 0),
            TableCalendar(
              headerVisible: false,
              firstDay: datesInSelectedMonth.first,
              lastDay: datesInSelectedMonth.last,
              focusedDay: _focusedDay,
              calendarFormat: _calendarFormat,
              weekendDays: const [DateTime.friday, DateTime.saturday],
              daysOfWeekHeight: 30,
              availableGestures: AvailableGestures.none,
              daysOfWeekStyle: DaysOfWeekStyle(
                weekdayStyle: const TextStyle(fontSize: 14, color: MyColors.black),
                weekendStyle: TextStyle(fontSize: 14, color: MyColors.black.withOpacity(0.5)),
              ),
              calendarBuilders: CalendarBuilders(
                selectedBuilder: (BuildContext context, DateTime dateTime1, DateTime dateTime2) {
                  return Container(
                    height: 50,
                    width: 50,
                    margin: const EdgeInsets.all(5),
                    decoration: const BoxDecoration(
                      shape: BoxShape.circle,
                      color: MyColors.darkIconColor,
                    ),
                    alignment: Alignment.center,
                    child: Text(
                      dateTime2.day.toString(),
                      style: const TextStyle(color: MyColors.white),
                    ),
                  );
                },
                defaultBuilder: (BuildContext context, DateTime dateTime1, DateTime dateTime2) {
                  int index = datesInSelectedMonth.indexWhere((element) => isSameDay(dateTime1, element));
                  if (index == -1) {
                    return Container(
                      height: 50,
                      width: 50,
                      margin: const EdgeInsets.all(5),
                      decoration: BoxDecoration(
                        border: Border.all(color: Colors.grey),
                        shape: BoxShape.circle,
                      ),
                      alignment: Alignment.center,
                      child: Text(
                        dateTime1.day.toString(),
                      ),
                    );
                  }
                  return Container(
                    height: 50,
                    width: 50,
                    margin: const EdgeInsets.all(5),
                    decoration: BoxDecoration(
                      border: Border.all(color: Colors.orange, width: 2),
                      shape: BoxShape.circle,
                    ),
                    alignment: Alignment.center,
                    child: Text(
                      dateTime1.day.toString(),
                    ),
                  );
                },
                disabledBuilder: (BuildContext context, DateTime dateTime1, DateTime selectedDt) {
                  return Container(
                    height: 50,
                    width: 50,
                    margin: const EdgeInsets.all(5),
                    decoration: BoxDecoration(
                      border: Border.all(color: Colors.grey),
                      shape: BoxShape.circle,
                    ),
                    alignment: Alignment.center,
                    child: Text(
                      dateTime1.day.toString(),
                    ),
                  );
                },
              ),
              headerStyle: const HeaderStyle(formatButtonVisible: false),
              selectedDayPredicate: (day) {
                // Use `selectedDayPredicate` to determine which day is currently selected.
                // If this returns true, then `day` will be marked as selected.

                // Using `isSameDay` is recommended to disregard
                // the time-part of compared DateTime objects.
                return isSameDay(_selectedDay, day);
              },
              onDaySelected: (selectedDay, focusedDay) {
                int index = datesInSelectedMonth.indexWhere((element) => isSameDay(selectedDay, element));

                if (index == -1) {
                  return;
                }
                if (!isSameDay(_selectedDay, selectedDay)) {
                  setState(() {
                    _selectedDay = selectedDay;
                    _focusedDay = focusedDay;
                  });

                  int dateIndex = widget.customTimeDateSlotList.indexWhere((element) {
                    DateTime dateFromList = DateFormat('dd MMMM, yyyy').parse(element.date!.date);
                    if (isSameDay(dateFromList, selectedDay)) {
                      return true;
                    }
                    return false;
                  });

                  if (dateIndex != -1) {
                    widget.onDateSelected(dateIndex);
                  }
                }
              },
            ),
          ],
        );
      },
    );
  }
}
