import { Fragment, FC } from "react";
import { useRouter } from "next/router";
import { useForm, Controller } from "react-hook-form";
import { X } from "lucide-react";
import { Transition, Dialog } from "@headlessui/react";
import type { IUserNotification } from "@plane/types";
import { Button, CustomSelect, TOAST_TYPE, setToast } from "@plane/ui";
import { DateDropdown } from "@/components/dropdowns";
// constants
import { allTimeIn30MinutesInterval12HoursFormat } from "@/constants/notification";
// ui
// types
// helpers
import { getDate } from "helpers/date-time.helper";

type SnoozeModalProps = {
  isOpen: boolean;
  onClose: () => void;
  onSuccess: () => void;
  notification: IUserNotification | null;
  onSubmit: (notificationId: string, dateTime?: Date | undefined) => Promise<void>;
};

type FormValues = {
  time: string | null;
  date: Date | null;
  period: "AM" | "PM";
};

const defaultValues: FormValues = {
  time: null,
  date: null,
  period: "AM",
};

const timeStamps = allTimeIn30MinutesInterval12HoursFormat;

export const SnoozeNotificationModal: FC<SnoozeModalProps> = (props) => {
  const { isOpen, onClose, notification, onSuccess, onSubmit: handleSubmitSnooze } = props;

  const router = useRouter();
  const { workspaceSlug } = router.query;

  const {
    formState: { isSubmitting },
    reset,
    handleSubmit,
    control,
    watch,
    setValue,
  } = useForm({
    defaultValues,
  });

  const getTimeStamp = () => {
    const today = new Date();
    const formDataDate = watch("date");

    if (!formDataDate) return timeStamps;

    const isToday = today.toDateString() === getDate(formDataDate)?.toDateString();

    if (!isToday) return timeStamps;

    const hours = today.getHours();
    const minutes = today.getMinutes();

    return timeStamps.filter((optionTime) => {
      let optionHours = parseInt(optionTime.value.split(":")[0]);
      const optionMinutes = parseInt(optionTime.value.split(":")[1]);

      const period = watch("period");

      if (period === "PM" && optionHours !== 12) optionHours += 12;

      if (optionHours < hours) return false;
      if (optionHours === hours && optionMinutes < minutes) return false;

      return true;
    });
  };

  const onSubmit = async (formData: FormValues) => {
    if (!workspaceSlug || !notification || !formData.date || !formData.time) return;

    const period = formData.period;

    const time = formData.time.split(":");
    const hours = parseInt(
      `${period === "AM" ? time[0] : parseInt(time[0]) + 12 === 24 ? "00" : parseInt(time[0]) + 12}`
    );
    const minutes = parseInt(time[1]);

    const dateTime: Date | undefined = getDate(formData?.date);
    dateTime?.setHours(hours);
    dateTime?.setMinutes(minutes);

    await handleSubmitSnooze(notification.id, dateTime).then(() => {
      handleClose();
      onSuccess();
      setToast({
        title: "Notification snoozed",
        message: "Notification snoozed successfully",
        type: TOAST_TYPE.SUCCESS,
      });
    });
  };

  const handleClose = () => {
    // This is a workaround to fix the issue of the Notification popover modal close on closing this modal
    const closeTimeout = setTimeout(() => {
      onClose();
      clearTimeout(closeTimeout);
    }, 50);

    const timeout = setTimeout(() => {
      reset({ ...defaultValues });
      clearTimeout(timeout);
    }, 500);
  };

  return (
    <Transition.Root show={isOpen} as={Fragment}>
      <Dialog as="div" className="relative z-20" onClose={handleClose}>
        <Transition.Child
          as={Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-in duration-200"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
        </Transition.Child>

        <div className="fixed inset-0 z-20 overflow-y-auto">
          <div className="flex min-h-full items-center justify-center p-4 text-center">
            <Transition.Child
              as={Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
              enterTo="opacity-100 translate-y-0 sm:scale-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100 translate-y-0 sm:scale-100"
              leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
            >
              <Dialog.Panel className="relative w-full transform rounded-lg bg-custom-background-100 p-5 text-left shadow-custom-shadow-md transition-all sm:w-full sm:!max-w-2xl">
                <form onSubmit={handleSubmit(onSubmit)}>
                  <div className="flex items-center justify-between">
                    <Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
                      Customize Snooze Time
                    </Dialog.Title>

                    <div>
                      <button type="button" onClick={handleClose}>
                        <X className="h-5 w-5 text-custom-text-100" />
                      </button>
                    </div>
                  </div>

                  <div className="mt-5 flex flex-col gap-3 md:!flex-row md:items-center">
                    <div className="flex-1 pb-3 md:pb-0">
                      <h6 className="mb-2 block text-sm font-medium text-custom-text-400">Pick a date</h6>
                      <Controller
                        name="date"
                        control={control}
                        rules={{ required: "Please select a date" }}
                        render={({ field: { value, onChange } }) => (
                          <DateDropdown
                            value={value}
                            placeholder="Select date"
                            onChange={(val) => {
                              setValue("time", null);
                              onChange(val);
                            }}
                            minDate={new Date()}
                            buttonVariant="border-with-text"
                            buttonContainerClassName="w-full text-left"
                            buttonClassName="border-custom-border-300 px-3 py-2.5"
                            hideIcon
                          />
                        )}
                      />
                    </div>
                    <div className="flex-1">
                      <h6 className="mb-2 block text-sm font-medium text-custom-text-400">Pick a time</h6>
                      <Controller
                        control={control}
                        name="time"
                        rules={{ required: "Please select a time" }}
                        render={({ field: { value, onChange } }) => (
                          <CustomSelect
                            value={value}
                            onChange={onChange}
                            label={
                              <div className="truncate">
                                {value ? (
                                  <span>
                                    {value} {watch("period").toLowerCase()}
                                  </span>
                                ) : (
                                  <span className="text-sm text-custom-text-400">Select a time</span>
                                )}
                              </div>
                            }
                            optionsClassName="w-full"
                            input
                          >
                            <div className="mb-2 flex h-9 w-full overflow-hidden rounded">
                              <div
                                onClick={() => {
                                  setValue("period", "AM");
                                }}
                                className={`flex h-full w-1/2 cursor-pointer items-center justify-center text-center ${
                                  watch("period") === "AM"
                                    ? "bg-custom-primary-100/90 text-custom-primary-0"
                                    : "bg-custom-background-80"
                                }`}
                              >
                                AM
                              </div>
                              <div
                                onClick={() => {
                                  setValue("period", "PM");
                                }}
                                className={`flex h-full w-1/2 cursor-pointer items-center justify-center text-center ${
                                  watch("period") === "PM"
                                    ? "bg-custom-primary-100/90 text-custom-primary-0"
                                    : "bg-custom-background-80"
                                }`}
                              >
                                PM
                              </div>
                            </div>
                            {getTimeStamp().length > 0 ? (
                              getTimeStamp().map((time, index) => (
                                <CustomSelect.Option key={`${time}-${index}`} value={time.value}>
                                  <div className="flex items-center">
                                    <span className="ml-3 block truncate">{time.label}</span>
                                  </div>
                                </CustomSelect.Option>
                              ))
                            ) : (
                              <p className="p-3 text-center text-custom-text-200">No available time for this date.</p>
                            )}
                          </CustomSelect>
                        )}
                      />
                    </div>
                  </div>

                  <div className="mt-5 flex items-center justify-between gap-2">
                    <div className="flex w-full items-center justify-end gap-2">
                      <Button variant="neutral-primary" size="sm" onClick={handleClose}>
                        Cancel
                      </Button>
                      <Button variant="primary" size="sm" type="submit" loading={isSubmitting}>
                        {isSubmitting ? "Submitting..." : "Submit"}
                      </Button>
                    </div>
                  </div>
                </form>
              </Dialog.Panel>
            </Transition.Child>
          </div>
        </div>
      </Dialog>
    </Transition.Root>
  );
};