import { useAuth0 } from '@auth0/auth0-react';
import DateFnsUtils from '@date-io/date-fns';
import { CircularProgress } from '@material-ui/core';
import { DatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers';
import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date';
// import { ReactComponent as ViewIcon } from 'assets/icons/view.svg';
import { ReactComponent as OwnerIcon } from 'assets/icons/avatar.svg';
import { ReactComponent as CloseIcon } from 'assets/icons/close.svg';
// import { Label } from 'shared/types';
import { ReactComponent as LabelIcon } from 'assets/icons/label.svg';
import classNames from 'classnames';
import { AssigneeMenu } from 'components/menus/AssigneeMenu';
import { LabelMenu } from 'components/menus/LabelMenu';
import { PriorityMenu } from 'components/menus/PriorityMenu';
import { StatusMenu } from 'components/menus/StatusMenu';
import { showError, showInfo } from 'components/Notification';
import { PriorityIcon } from 'components/PriorityIcon';
import { StatusIcon } from 'components/StatusIcon';
import { useClickOutside } from 'hooks/useClickOutside';
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { Label, Member } from 'shared/types';
import { getLabelObj, getPriorityString, getStatusText } from 'shared/utils/common';
import { formatDate } from 'shared/utils/formatDate';
import { getTaskDetail, updateTaskMicroProperties } from 'store/actions/taskActions';
import { UPDATE_TASK_MICRO_PROPS_CLEAR } from 'store/contants/taskConstants';
import { RootState } from 'store/store';
interface Props {
  // Show menu (for small screen only)
  showMenu: boolean;
  onCloseMenu?: () => void;
  onCreateIssue?: Function;
  onOpenHelp?: Function;
  onOpenInviteBox?: Function;
}

interface URLParams {
  taskId: string;
  projectId: string;
}


export const RightSideBar: React.FC<Props> = ({ showMenu, onCloseMenu }) => {

  const ref = useRef<HTMLDivElement>() as RefObject<HTMLDivElement>;
  const { task } = useSelector((state: RootState) => state.taskDetail);
  const { error, loading, success } = useSelector((state: RootState) => state.updateTask);
  const dispatch = useDispatch();
  const params = useParams<URLParams>();
  const { getAccessTokenSilently } = useAuth0();
  const classes = classNames(
    `absolute lg:static inset-0 transform duration-300 lg:relative lg:translate-x-0 bg-white flex flex-col flex-shrink-0 w-80 font-sans text-sm text-gray-700 border-l border-gray-100 lg:shadow-none justify-items-start h-screen`,
    {
      '-translate-x-full ease-out shadow-none': !showMenu,
      'translate-x-0 ease-in shadow-xl': showMenu
    }
  );
  const [startDate, setStartDate] = useState<MaterialUiPickersDate>(task.startDate);
  const [dueDate, setDueDate] = useState<MaterialUiPickersDate>(task.dueDate);
  const [priority, setPriority] = useState(task.priority);
  const [label, setLabel] = useState(task.label);
  const [status, setStatus] = useState(task.status);
  const [assignee, setAssignee] = useState<Member>(task.assignee);
  const [edited, setEdited] = useState(false);

  // Date Pickers
  const [isOpenStartDate, setIsOpenStartDate] = useState(false);
  const [isOpenDueDate, setIsOpenDueDate] = useState(false);

  const onStartDatePick = () => {
    setIsOpenStartDate(true);
  };
  const onDueDatePick = () => {
    setIsOpenDueDate(true);
  };


  let ready = false;
  useClickOutside(ref, () => {
    if (ready && showMenu && onCloseMenu)
      onCloseMenu();
  });

  const onCancel = useCallback(() => {
    setPriority(task.priority);
    setLabel(task.label);
    setDueDate(task.dueDate);
    setStartDate(task.startDate);
    setAssignee(task.assignee);
    setStatus(task.status);
    setEdited(false);
  }, [task]);
  const onSave = async () => {
    const fieldsToUpdate = {
      status: task.status !== status,
      priority: task.priority !== priority,
      startDate: task.startDate !== startDate,
      dueDate: task.dueDate !== dueDate,
      label: task.label !== label,
      assignee: task?.assignee?.user?._id !== assignee?.user?._id
    };
    const body: any = {};
    if (fieldsToUpdate.dueDate) body.dueDate = dueDate;
    if (fieldsToUpdate.startDate) body.startDate = startDate;
    if (fieldsToUpdate.assignee) body.assignee = assignee._id;
    if (fieldsToUpdate.priority) body.priority = priority;
    if (fieldsToUpdate.status) body.status = status;
    if (fieldsToUpdate.label) body.label = label;

    const token = await getAccessTokenSilently();
    dispatch(updateTaskMicroProperties(params.taskId, params.projectId, token, body));
  };

  useEffect(() => {
    // eslint-disable-next-line react-hooks/exhaustive-deps
    setTimeout(() => ready = true, 300);
  });
  useEffect(() => {
    if (priority !== task.priority) setEdited(true);
    if (label !== task.label) setEdited(true);
    if (status !== task.status) setEdited(true);
    if (startDate !== task.startDate) setEdited(true);
    if (dueDate !== task.dueDate) setEdited(true);
    if (assignee?.user?._id !== task?.assignee?.user?._id) setEdited(true);
  }, [priority, label, status, assignee, edited, task.priority, task.label, task.status, task.startDate, task.dueDate, startDate, dueDate, task?.assignee?.user?._id]);

  useEffect(() => {
    if (error) {
      showError('Please try again later.', 'Unable to Update Task.');
      onCancel();
      dispatch({ type: UPDATE_TASK_MICRO_PROPS_CLEAR });
    }
    if (success) {
      showInfo('', 'Task Updated Successfully');
      setEdited(false);
      getAccessTokenSilently().then(token => {
        dispatch(getTaskDetail(token, params.projectId, params.taskId));
        dispatch({ type: UPDATE_TASK_MICRO_PROPS_CLEAR });
      });
    }
  }, [success, error, onCancel, dispatch, getAccessTokenSilently, params]);

  return (
    <>
      <div className={classes} style={{ zIndex: 3 }} ref={ref}>
        <button
          className='flex-shrink-0 px-5 ml-2 lg:hidden h-14 focus:outline-none'
          onClick={onCloseMenu}
        >
          <CloseIcon className='w-4' />
        </button>

        {/* Top menu*/}
        {loading ? <div className='flex items-center justify-center flex-1'><CircularProgress color="primary" /></div> : <div className='flex flex-col flex-grow-0 flex-shrink-0 px-5 py-3 pt-10'>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Status</p>
            <div className='flex items-center mr-auto'>
              <StatusMenu
                id='status-menu'
                button={<button className='flex items-center justify-center w-6 h-6 border-none rounded focus:outline-none hover:bg-gray-100'><StatusIcon status={status} /></button>}
                onSelect={(st) => {
                  setStatus(st);
                }}
              />
              <p className='text-gray-500 ml-2'>{getStatusText(status)}</p>
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Priority</p>
            <div className='flex items-center mr-auto'>
              <PriorityMenu
                // id='priority-menu'
                button={<button
                  className='inline-flex items-center h-6 px-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'
                >
                  {priority && <PriorityIcon priority={priority} />}
                </button>}
                onSelect={(val) => setPriority(val)}
              />
              <p className='text-gray-500 ml-2'>{getPriorityString(priority)}</p>
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Assignee</p>
            <div className='flex items-center mr-auto'>
              <AssigneeMenu
                button={<button className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {!assignee ? <><OwnerIcon className='w-3.5 h-3.5 mr-2' />
                    <span>Unassigned</span></> : <><OwnerIcon className='w-3.5 h-3.5 mr-2' />
                    <span>{`${assignee?.user?.firstName} ${assignee?.user?.lastName}`}</span></>}
                </button>}
                onSelect={(assignee: Member) => setAssignee(assignee)}
              />
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Label</p>
            <div className='flex items-center mr-auto'>
              <LabelMenu
                id='label-menu'
                onSelect={(label: Label) => setLabel(label.name)}
                button={<button className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {label === 'No Label' ? <><LabelIcon className='w-3.5 h-3.5  mr-2' /> <span>No Label</span> </> : <><div className="w-2.5 h-2.5 rounded-full mr-2" style={{ background: getLabelObj(label)?.color }}></div> <span>{getLabelObj(label)?.name}</span> </>}
                </button>} />
            </div>
          </div>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>

            <div className='flex justify-between items-center mb-6'>
              <p className='text-gray-400 font-medium w-28'>Start Date</p>
              <div className='flex items-center mr-auto'>
                <DatePicker
                  disablePast
                  open={isOpenStartDate}
                  onOpen={() => setIsOpenStartDate(true)}
                  onClose={() => setIsOpenStartDate(false)}
                  TextFieldComponent={() => null}
                  variant='dialog'
                  onChange={(date: MaterialUiPickersDate) => setStartDate(date)}
                  value={startDate}
                />
                <button onClick={onStartDatePick} className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {startDate ? `${formatDate(startDate)}` : "Start Date"}
                </button>
              </div>
            </div>
            <div className='flex justify-between items-center mb-6'>
              <p className='text-gray-400 font-medium w-28'>Due Date</p>
              <div className='flex items-center mr-auto'>
                <DatePicker
                  disablePast
                  open={isOpenDueDate}
                  onOpen={() => setIsOpenDueDate(true)}
                  onClose={() => setIsOpenDueDate(false)}
                  TextFieldComponent={() => null}
                  variant='dialog'
                  onChange={(date: MaterialUiPickersDate) => setDueDate(date)}
                  value={dueDate}
                />
                <button onClick={onDueDatePick} className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {dueDate ? `${formatDate(dueDate)}` : "Due Date"}
                </button>
              </div>
            </div>
            <div className='flex justify-around mt-4'>
              {edited && <><button onClick={onCancel} className='inline-flex items-center justify-center px-4 py-2 transition-all rounded-md border border-gray-200 text-gray-500 hover:bg-gray-100 rouned hover:text-gray-700 w-28'>Cancel</button>
                <button onClick={onSave} className='ml-3 inline-flex items-center justify-center px-4 py-2 transition-all duration-400 bg-indigo-700 rounded-md  hover:bg-indigo-800 rouned w-5/12 text-white'>Save</button></>}
            </div>
          </MuiPickersUtilsProvider>
        </div>}
      </div>
    </>
  );
};