import {
  fullMonthsMapping,
  hourlySlots,
  monthsMapping,
  daysMapping,
} from "@/utils/date-time-utils";
import { formatScheduleDate, parseJsonSafely } from "@/utils/utils";
import moment from "moment";
import React, { useState } from "react";
import { Calendar } from "react-calendar";
import CalendarIcon from "./icons/CalendarIcon";
import NextIcon from "./icons/NextIcon";
import PrevIcon from "./icons/PrevIcon";

const DateTimePicker = ({
  defaultDate,
  register,
  fieldNames,
  setValue,
  showCalendar,
  setShowCalendar,
  toDefault,
  fromDefault,
  bookedSlots,
  scheduleTemplate,
  defaultMessage,
}) => {
  const [selectedDate, setSelectedDate] = useState(defaultDate ?? new Date());
  const [from, setFrom] = useState(fromDefault ?? "");
  const [to, setTo] = useState(toDefault ?? "");
  const [error, setError] = useState("");

  // Helper to check if a slot is booked
  const isSlotBooked = (slotTime) => {
    if (!bookedSlots || !Array.isArray(bookedSlots)) return false;
    // Only check slots for the selected date
    const selectedDateStr = moment(selectedDate).format("YYYY-MM-DD");
    return bookedSlots.some((booking) => {
      // booking should have start and end in ISO or parseable format
      const bookingStart = moment(booking.start);
      const bookingEnd = moment(booking.end);
      // Only check if booking is on the same day
      if (bookingStart.format("YYYY-MM-DD") !== selectedDateStr) return false;
      // If slotTime is within booking range
      return (
        slotTime >= bookingStart.toDate() && slotTime < bookingEnd.toDate()
      );
    });
  };

  // Validate time range
  const isTimeRangeValid = () => {
    if (!from || !to) return false;
    const formattedDate = moment(selectedDate).format("MM/DD/YY");
    const fromTime = new Date(formattedDate + " " + from);
    const toTime = new Date(formattedDate + " " + to);
    return fromTime < toTime;
  };

  const onApply = () => {
    if (!isTimeRangeValid()) {
      setError("Start time must be before end time.");
      return;
    }
    setError("");
    setValue("from", from);
    setValue("to", to);
    setValue("selectedDate", selectedDate);
    setShowCalendar(false);
  };

  return (
    <div
      className={showCalendar ? "popup-mobile z-50" : ""}
      onClick={() => setShowCalendar((prev) => !prev)}
    >
      {fieldNames.map((field, idx) => (
        <input key={idx} type='hidden' {...register(field)} />
      ))}

      <button
        type='button'
        className={`${
          showCalendar ? "" : "border-2"
        } flex w-full items-center gap-2 p-2 pr-16 md:relative md:border-2`}
        onClick={(e) => {
          setShowCalendar((prev) => !prev);
          e.stopPropagation();
        }}
      >
        <div className={`md:inline ${showCalendar ? "hidden" : ""}`}>
          <CalendarIcon />
        </div>
        <span
          id='booking-time'
          className={
            showCalendar
              ? "hidden"
              : "inline whitespace-nowrap text-sm md:text-base"
          }
        >
          {from && to
            ? monthsMapping[selectedDate.getMonth()] +
              " " +
              selectedDate.getDate() +
              "/" +
              selectedDate.getFullYear() +
              " - " +
              from +
              " to " +
              to
            : defaultMessage ?? "Select date and time"}
        </span>
        {
          <div
            className={`${
              showCalendar ? "block" : "hidden"
            } absolute bottom-[15px] left-0 right-0 top-[0%] mx-auto min-h-[55vh] w-[80vw] overflow-y-auto border-2 bg-white text-center text-sm shadow-lg md:-left-10 md:-top-[22.5rem] md:right-[unset] md:max-h-[unset] md:w-[unset] lg:left-[-150px] 2xl:-top-[20rem]`}
            onClick={(e) => e.stopPropagation()}
          >
            <div className='flex items-center justify-between border-b p-[16px]'>
              <h3 className='text-xl font-semibold'>Select date and time</h3>
              <button
                type='button'
                onClick={() => setShowCalendar(false)}
                className='rounded-full border p-1 px-3 text-2xl font-normal duration-100 hover:bg-gray-200 active:bg-gray-300'
              >
                &#x2715;
              </button>
            </div>
            <div className='flex flex-col md:flex-row'>
              <div className=''>
                <Calendar
                  onChange={(newDate) => {
                    setSelectedDate(newDate);
                    setFrom("");
                    setTo("");
                  }}
                  value={selectedDate}
                  className={`custom-calendar`}
                  nextLabel={<NextIcon />}
                  prevLabel={<PrevIcon />}
                  next2Label={<></>}
                  prev2Label={<></>}
                  tileDisabled={({ date }) => {
                    let customSlots = [];
                    try {
                      if (
                        scheduleTemplate?.custom_slots &&
                        Object.keys(scheduleTemplate?.custom_slots)?.length > 0
                      ) {
                        customSlots = JSON.parse(
                          scheduleTemplate?.custom_slots || "[]"
                        );
                      }
                    } catch (e) {
                      console.error("Invalid JSON in custom_slots", e);
                    }
                    if (
                      customSlots.length > 0 &&
                      customSlots[formatScheduleDate(date).toString()]
                        ?.length === 0
                    ) {
                      return true;
                    }
                    if (
                      scheduleTemplate?.id &&
                      scheduleTemplate[daysMapping[date.getDay()]] != 1
                    ) {
                      return true;
                    }
                  }}
                  minDate={new Date()}
                  maxDetail='month'
                />
                <p className='p-[16px] text-left text-[#667085]'>
                  Pacific Time - US & Canada
                </p>
                <div className='hidden cursor-default px-[16px] py-1 text-left md:flex'>
                  <p className='min-w-[150px]'>From - {from}</p>
                  <p>Until - {to}</p>
                </div>
              </div>
              <div className='p-2'>
                <p className='mb-4 text-center font-semibold'>
                  <span className='capitalize'>
                    {daysMapping[selectedDate.getDay()]}
                  </span>{" "}
                  , {fullMonthsMapping[selectedDate.getMonth()]}{" "}
                  {selectedDate.getDate()}
                </p>
                <div className='custom-calendar-scroll review-scroll flex max-h-[150px] flex-col gap-[12px] overflow-y-auto overflow-x-hidden px-3 text-[#667085] md:max-h-[270px] md:px-6'>
                  {hourlySlots.map((tm, idx) => {
                    var formattedDate = moment(selectedDate).format("MM/DD/YY");
                    var fromTime = new Date(formattedDate + " " + from);
                    var toTime = new Date(formattedDate + " " + to);
                    var slotTime = new Date(formattedDate + " " + tm);
                    var slotTimeOnly = new Date("01/01/2001" + " " + tm);
                    var json = scheduleTemplate.custom_slots ?? "[]";
                    var custom_slots_obj = parseJsonSafely(json, {});
                    var custom_slots = custom_slots_obj[formattedDate] ?? [];
                    custom_slots = custom_slots.map((slot) => ({
                      fromTime: new Date(slot.start),
                      toTime: new Date(slot.end),
                    }));
                    var template_slots = Array.isArray(scheduleTemplate.slots)
                      ? scheduleTemplate.slots.map((slot) => ({
                          fromTime: new Date(slot.start),
                          toTime: new Date(slot.end),
                        }))
                      : [];

                    // --- NEW: Check if slot is booked ---
                    const slotBooked = isSlotBooked(slotTime);

                    return (
                      <button
                        type='button'
                        key={idx}
                        className={`${
                          from == tm || to == tm
                            ? "border-2 border-black"
                            : "border border-[#EAECF0] disabled:bg-[#F2F4F7] disabled:line-through"
                        }  w-full py-[8px] text-center md:w-[152px] ${
                          from &&
                          to &&
                          fromTime <= slotTime &&
                          toTime >= slotTime
                            ? "between-slots font-semibold"
                            : ""
                        }`}
                        onClick={(e) => {
                          if (from == tm) {
                            setFrom("");
                            setTo("");
                            setError("");
                            return;
                          }
                          if (to == tm) {
                            setTo("");
                            setError("");
                            return;
                          }
                          if (from == "") {
                            setFrom(e.target.innerText);
                            setError("");
                          } else {
                            // Only allow setting 'to' if after 'from'
                            const formattedDate =
                              moment(selectedDate).format("MM/DD/YY");
                            const fromTime = new Date(
                              formattedDate + " " + from
                            );
                            const toTime = new Date(formattedDate + " " + tm);
                            if (toTime <= fromTime) {
                              setError("End time must be after start time.");
                              return;
                            } else {
                              setError("");
                              setTo(e.target.innerText);
                            }
                          }
                        }}
                        disabled={(() => {
                          // disabled slots that are not available in template only if a custom slot was not defined for the selectedDay
                          // if custom slots were defined for selectedDay then disable slots that are not included

                          // disable if time is < current time
                          if (slotTime < new Date()) return true;

                          // --- NEW: Disable if slot is booked ---
                          if (slotBooked) return true;

                          if (custom_slots.length > 0) {
                            var shouldDisable = false;
                            for (let i = 0; i < custom_slots.length; i++) {
                              const slot = custom_slots[i];
                              if (
                                slot.fromTime <= slotTime &&
                                slot.toTime >= slotTime
                              ) {
                                shouldDisable = false;
                                break;
                              } else {
                                shouldDisable = true;
                              }
                            }
                            if (shouldDisable) return true;
                          } else {
                            var shouldDisable = false;
                            for (let i = 0; i < template_slots.length; i++) {
                              const slot = template_slots[i];
                              if (
                                slot.fromTime <= slotTimeOnly &&
                                slot.toTime >= slotTimeOnly
                              ) {
                                shouldDisable = false;
                                break;
                              } else {
                                shouldDisable = true;
                              }
                            }
                            if (shouldDisable) return true;
                          }
                        })()}
                      >
                        {tm}
                      </button>
                    );
                  })}
                </div>
                {/* Error message for invalid time range */}
                {error && (
                  <div className='mt-2 text-sm text-red-500'>{error}</div>
                )}
                <div className='mt-8 px-6'>
                  <button
                    type='button'
                    className='login-btn-gradient w-[152px] rounded-sm py-[8px] text-center text-white'
                    disabled={from == "" || to == "" || !isTimeRangeValid()}
                    onClick={onApply}
                  >
                    Apply
                  </button>
                </div>
                <div className='mt-2 flex cursor-default px-1 py-1 text-left md:hidden'>
                  <p className='min-w-[150px]'>From - {from}</p>
                  <p>Until - {to}</p>
                </div>
              </div>
            </div>
          </div>
        }
      </button>
    </div>
  );
};

export default DateTimePicker;
