import React, { useEffect, useId } from "react";
import "./date-range-picker-styles.scss";
import Button from "../button/Button";
import { Popover, PopoverContent, PopoverTrigger } from "../popover/Popover";
import { DateRange, DayPicker } from "react-day-picker";
import Option from "../option/Option";
import {
  DateRangePickerProps,
  DefaultRangeOption,
} from "@app/models/components";
import { useDateRangePicker } from "./DateRangePickerContext";
import { cloneDeep } from "lodash";

const DateRangePicker: React.FC<DateRangePickerProps> = ({
  range,
  defaultOptions = [],
  showTitle,
  applyButtonTitle = "Apply",
  cancelButtonTitle = "Cancel",
  showCancelButton = true,
  fromDate = new Date(new Date().setFullYear(new Date().getFullYear() - 3)),
  toDate = new Date(new Date().setFullYear(new Date().getFullYear() + 3)),
  label = "",
  onChange,
  disabled,
  icon,
}) => {
  if (!onChange || !range) {
    return null;
  }

  const { setIsCustomRange } = useDateRangePicker();

  const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
  const [selectedRange, setSelectedRange] = React.useState<DateRange>(range);
  const [selectedOption, setSelectedOption] = React.useState<
    DefaultRangeOption | undefined
  >();

  const triggerID = useId();

  // Display range inside trigger
  const formatting: any = {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
  };
  const formattedStartDate =
    selectedRange?.from?.toLocaleDateString("en-UK", formatting) ?? "";
  const formattedEndDate =
    selectedRange?.to?.toLocaleDateString("en-UK", formatting) ?? "";
  const hyphen = formattedStartDate && formattedEndDate ? " - " : "";
  const triggerText = `${formattedStartDate}${hyphen}${formattedEndDate}`;

  // Display option title inside trigger
  const buttonStartText = selectedOption?.title ?? "Custom";
  const buttonStartEl = showTitle && (
    <span className="drp-triggerTitle">{buttonStartText}</span>
  );

  const handleApplyBtnClick = () => {
    if (range.from !== selectedRange.from || range.to !== selectedRange.to) {
      const isCustom = selectedOption ? false : true;
      onChange(selectedRange, isCustom);
      setIsCustomRange?.(isCustom);
    }
    setIsPopoverOpen(false);
  };

  const handleCancelBtnClick = () => {
    setSelectedRange(range);
    setIsPopoverOpen(false);
  };

  const handleRangeSelect = (range?: DateRange) => {
    if (!range) {
      return;
    }

    setSelectedRange(range);
  };

  const handleSelectDefaultOption = (value: DateRange) => {
    handleRangeSelect(value);
  };

  const handlePopoverOpenChange = (isOpen: boolean) => {
    setIsPopoverOpen(isOpen);

    if (!isOpen) {
      setSelectedRange(range);
    }
  };

  const applyButtonDisabled = !selectedRange?.from || !selectedRange?.to;
  const showDefaultOptions = defaultOptions.length > 0;

  const areDatesEqual = (date1: Date, date2: Date): boolean => {
    const year1 = date1.getFullYear();
    const month1 = date1.getMonth();
    const day1 = date1.getDate();

    const year2 = date2.getFullYear();
    const month2 = date2.getMonth();
    const day2 = date2.getDate();

    return year1 === year2 && month1 === month2 && day1 === day2;
  };

  useEffect(() => {
    setSelectedRange(range);
  }, [range]);

  useEffect(() => {
    const selectedOption = defaultOptions.find((option) => {
      if (
        option.range.from &&
        option.range.to &&
        selectedRange.from &&
        selectedRange.to
      ) {
        return (
          areDatesEqual(option.range.from, selectedRange.from) &&
          areDatesEqual(option.range.to, selectedRange.to)
        );
      }
      return false;
    });

    setSelectedOption(selectedOption ? selectedOption : undefined);
  }, [selectedRange]);

  return (
    <div className="drp-root">
      <Popover open={isPopoverOpen} onOpenChange={handlePopoverOpenChange}>
        <div className="drp-trigger">
          {label && <label htmlFor={triggerID}>{label}</label>}
          <PopoverTrigger asChild>
            <button
              disabled={disabled}
              id={triggerID}
              className="drp-triggerButton"
            >
              {buttonStartEl}
              <span className="drp-triggerText">{triggerText}</span>
              <div className="drp-icon"> {icon}</div>
            </button>
          </PopoverTrigger>
        </div>

        <PopoverContent asChild>
          <div className="drp-dropdownContent">
            <div className="drp-datePicker">
              {showDefaultOptions && (
                <ul className="drp-defaultDatesList">
                  {defaultOptions.map((option, index) =>
                    option.title ? (
                      <Option
                        key={`${option.title}-${index}`}
                        value={option.range}
                        text={option.title}
                        onClick={handleSelectDefaultOption}
                        selected={selectedOption?.title === option.title}
                      />
                    ) : null
                  )}
                </ul>
              )}
              <div className="drp-calendar">
                <DayPicker
                  mode="range"
                  selected={selectedRange}
                  onSelect={handleRangeSelect}
                  fromDate={fromDate}
                  toDate={toDate}
                  numberOfMonths={2}
                  defaultMonth={selectedRange.to}
                />
              </div>
            </div>
            <div className="drp-footer">
              {showCancelButton && (
                <Button
                  onClickHandler={handleCancelBtnClick}
                  text={cancelButtonTitle}
                  variant="tertiary"
                />
              )}
              <Button
                onClickHandler={handleApplyBtnClick}
                text={applyButtonTitle}
                variant="tertiary"
                disabled={applyButtonDisabled}
              />
            </div>
          </div>
        </PopoverContent>
      </Popover>
    </div>
  );
};

export default DateRangePicker;
