import React, { useCallback, useEffect, useMemo, useState } from 'react';
import autosize from 'autosize';
import { bem } from 'utils/bem';
import { Id, ProjectReviewer } from 'backend-api/models';
import { Body, H3, PrimaryLabel } from 'common/components/typography';
import { Icon } from 'common/components/icon';
import { Button } from 'common/components/button';
import { ApproversSelect } from './components';
import { getWarningMessage, isReviewersHasProjectAccess } from './transducers';
import { BEM_CLASS, SRequestApprovalModal } from './s-request-approval-modal';
import { REVIEWERS_DROPDOWN_IDENTIFIER } from './constants';
import { RequestApprovalModalInfo } from './types';

interface RequestApprovalModalProps {
  className?: string;
  reviewers: ProjectReviewer[];
  isConfidentialProject: boolean;
  initialInfo?: RequestApprovalModalInfo;
  onConfirm(reviewers: Id[], message?: string): void;
  onCancel(reviewers: Id[], message?: string): void;
}

const classes = bem(BEM_CLASS);

export const RequestApprovalModal = React.memo(
  ({ className, reviewers, isConfidentialProject, onConfirm, onCancel, initialInfo }: RequestApprovalModalProps) => {
    const rootRef = React.useRef<HTMLDivElement>(null);
    const textareaRef = React.useRef<HTMLTextAreaElement>(null);

    const [message, setMessage] = useState(initialInfo?.message || '');
    const [selectedReviewers, setSelectedReviewers] = useState<Id[]>(initialInfo?.reviewers || []);
    const [isFormValid, setIsFormValid] = useState(true);

    const selectOptions = useMemo(
      () => reviewers.map(({ id, name, email, hasProjectAccess }) => ({ id, value: name, email, hasProjectAccess })),
      [reviewers]
    );

    const isSelectedReviewersHasProjectAccess = useMemo(
      () => isReviewersHasProjectAccess(reviewers, selectedReviewers),
      [reviewers, selectedReviewers]
    );

    const warningMessage = useMemo(() => getWarningMessage(isConfidentialProject), [isConfidentialProject]);

    const onMessageChange = useCallback(
      (e: React.ChangeEvent<HTMLTextAreaElement>) => {
        setMessage(e.target.value);
      },
      [setMessage]
    );

    const onReviewersSelect = useCallback((ids: Id[]) => {
      setSelectedReviewers(ids);
    }, []);

    const onApproveRequest = useCallback(() => {
      if (selectedReviewers.length === 0) {
        setIsFormValid(false);
      } else {
        onConfirm(selectedReviewers, message);
      }
    }, [message, onConfirm, selectedReviewers]);

    useEffect(() => {
      const textareaElement = textareaRef.current;

      autosize(textareaElement);

      return () => {
        autosize.destroy(textareaElement);
      };
    }, []);

    useEffect(() => {
      const onClickOutside = (e: MouseEvent) => {
        const isRootAndTargetExist = rootRef.current && e.target instanceof Element;

        if (
          isRootAndTargetExist &&
          !rootRef.current.contains(e.target) &&
          !e.target.closest(`.${REVIEWERS_DROPDOWN_IDENTIFIER}`)
        ) {
          onCancel(selectedReviewers, message);
        }
      };

      document.addEventListener('mousedown', onClickOutside, { capture: true });

      return () => {
        document.removeEventListener('mousedown', onClickOutside, { capture: true });
      };
    }, [message, onCancel, selectedReviewers]);

    const handleCancel = useCallback(() => {
      onCancel(selectedReviewers, message);
    }, [message, onCancel, selectedReviewers]);

    useEffect(() => {
      setIsFormValid(true);
    }, [selectedReviewers]);

    return (
      <SRequestApprovalModal ref={rootRef} className={className}>
        <div className={classes('content')}>
          <div className={classes('header')}>
            <H3 className={classes('title')}>Request Approval</H3>
            <button className={classes('close')} onClick={handleCancel} tabIndex={-1}>
              <Icon className={classes('close-icon')} color="inherit" name="close" size="general" />
            </button>
          </div>

          {!isSelectedReviewersHasProjectAccess && (
            <div className={classes('warning')}>
              <div className={classes('warning-icon')}>
                <Icon color="inherit" name="info" size="general" />
              </div>
              {warningMessage}
            </div>
          )}

          <Body className={classes('text')}>
            Select a colleague to send an approval email to. Please note, only Sony employees can access Decibel.
          </Body>

          <ApproversSelect
            className={classes('reviewers')}
            selectedOptions={selectedReviewers}
            onOptionSelect={onReviewersSelect}
            options={selectOptions}
            dropdownIdentifier={REVIEWERS_DROPDOWN_IDENTIFIER}
            hasError={!isFormValid}
          />

          <PrimaryLabel className={classes('textarea-label')}>Message (optional)</PrimaryLabel>

          <textarea
            ref={textareaRef}
            className={classes('textarea')}
            value={message}
            placeholder="Type your message..."
            maxLength={500}
            onChange={onMessageChange}
          />
        </div>
        <div className={classes('footer')}>
          <Button
            className={classes('cancel-button')}
            variant="secondary-gray"
            onClick={handleCancel}
            dataSelector="request-approval-modal-cancel-button"
          >
            Cancel
          </Button>

          <Button variant="primary-cta" onClick={onApproveRequest} dataSelector="request-approval-modal-confirm-button">
            Confirm
          </Button>
        </div>
      </SRequestApprovalModal>
    );
  }
);
