import React, { useState, useRef } from 'react';
import classNames from 'classnames/bind';
import ReactDatepicker, { registerLocale } from 'react-datepicker';
import DateSVG from 'assets/svg/date.svg';
import ArrowSVG from 'assets/svg/arrow.svg';
import is from 'date-fns/locale/is';
import 'react-datepicker/dist/react-datepicker.css';

import s from './DatePickers.module.scss';

const cn = classNames.bind(s);

registerLocale('is', is);

interface IDatePickersProps {
  color: string;
  from: Date;
  to: Date;
  fromLabel: string;
  toLabel: string;
  onChangeDate: (date: Date, type: string) => void;
  onChangeYear: (year: string) => void;
  isMobile: boolean;
  years?: number[];
}

type PickerType = 'from' | 'to';

export const DatePickers = ({
  color,
  from,
  to,
  fromLabel,
  toLabel,
  onChangeDate,
  onChangeYear,
  isMobile,
  years,
}: IDatePickersProps) => {
  const [isFromPickerOpen, SetIsFromPickerOpen] = useState(false);
  const [isToPickerOpen, SetIsToPickerOpen] = useState(false);
  const [wasClickOutside, SetWasClickOutside] = useState(false);

  const fromRef = useRef(null);
  const toRef = useRef(null);

  const handleClick = (type: PickerType) => {
    if (wasClickOutside) {
      // Triggered by outside click reset wasClickOutside and do nothing
      SetWasClickOutside(false);
    } else {
      // Not triggered by outside click --> open picker
      switch (type) {
        case 'from':
          if (!isFromPickerOpen) {
            SetIsFromPickerOpen(true);
            SetIsToPickerOpen(false);
          }
          break;
        case 'to':
          if (!isToPickerOpen) {
            SetIsToPickerOpen(true);
            SetIsFromPickerOpen(false);
          }
          break;
        default:
          break;
      }
    }
  };

  const handleOutsideClick = (e: React.MouseEvent, type: PickerType) => {
    /**
     * Outside clicks, outside the month view datepicker, will also trigger handleClick when the click is on the datePickers__date element.
     * Outside clicks should close the datepicker but when it also triggers handleClick then handleClick opens it right back.
     * To prevent that handleOutsideClick sets wasClickOutside to true when the outside click will also trigger handleClick.
     * stopPropagation did not work on the click event.
     * This is a candidate for a better solution.
     */

    // Which picker ref to check
    const ref = type === 'from' ? fromRef : toRef;

    // Check if the outside click is inside datePickers__date element area
    const isInside = (ref.current ?? new Node()).contains(e.target as Node);

    if (isInside) {
      // Set wasClickOutside to true so that handleClick knows not to open the picker.
      SetWasClickOutside(true);
    }

    // Close pickers
    type === 'from' ? SetIsFromPickerOpen(false) : SetIsToPickerOpen(false);
  };

  return (
    <div className={s.datePickers}>
      <div
        className={cn(s.datePickers__date, `color-${color}`, 'from')}
        onClick={() => handleClick('from')}
        ref={fromRef}
      >
        <div className={cn(s.datePickers__icon, `color-${color}`)}>
          <DateSVG className={s.datePickers__iconSVG} />
        </div>
        <label className={s.datePickers__label}>{fromLabel}</label>
        {typeof window !== 'undefined' && (
          <div className={s.datePickers__datepicker}>
            <ReactDatepicker
              open={isFromPickerOpen}
              onClickOutside={(e) => {
                handleOutsideClick(e, 'from');
              }}
              selected={from}
              onChange={(dateTime: Date) => onChangeDate(dateTime, 'from')}
              dateFormat="d.M.yyyy"
              timeFormat="HH:mm"
              locale="is"
              disabled={isToPickerOpen} // To prevent bug where both inputs are focused at the same time
              popperModifiers={{
                offset: {
                  enabled: true,
                  offset: isMobile ? '-101px, 10px' : '-101px, 35px',
                },
              }}
            />
          </div>
        )}
        <ArrowSVG className={cn(s.datePickers__arrow, { isOpen: isFromPickerOpen })} />
      </div>

      <div
        className={cn(s.datePickers__date, `color-${color}`, 'to')}
        onClick={() => handleClick('to')}
        ref={toRef}
      >
        {isMobile && (
          <div className={cn(s.datePickers__icon, `color-${color}`)}>
            <DateSVG className={s.datePickers__iconSVG} />
          </div>
        )}
        <label className={s.datePickers__label}>{toLabel}</label>
        {typeof window !== 'undefined' && (
          <div className={s.datePickers__datepicker}>
            <ReactDatepicker
              open={isToPickerOpen}
              onClickOutside={(e) => {
                handleOutsideClick(e, 'to');
              }}
              selected={to}
              minDate={from}
              onChange={(dateTime: Date) => onChangeDate(dateTime, 'to')}
              dateFormat="d.M.yyyy"
              timeFormat="HH:mm"
              locale="is"
              disabled={isFromPickerOpen} // To prevent bug where both inputs are focused at the same time
              popperModifiers={{
                offset: {
                  enabled: true,
                  offset: isMobile ? '-92px, 10px' : '-48px, 35px',
                },
              }}
            />
          </div>
        )}
        <ArrowSVG className={cn(s.datePickers__arrow, { isOpen: isToPickerOpen })} />
      </div>
      {years && (
        <div className={s.datePickers__years}>
          {years.map((year) => (
            <button
              key={year}
              className={cn(s.datePickers__year, `color-${color}`)}
              onClick={() => onChangeYear(year.toString())}
            >
              {year}
            </button>
          ))}
        </div>
      )}
    </div>
  );
};
