import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { bem } from 'utils/bem';
import {
  Button,
  BUTTON_TYPE,
  SearchField,
  Textarea,
  Alert,
  ALERT_TYPE,
  ALERT_SIZE,
  THEME,
  Typography,
  TYPOGRAPHY_TYPE,
} from 'gdb-web-shared-components';
import { Id, ProjectReviewer } from 'backend-api/models';
import { Modal, ModalContentProps, ModalHeader, UserSearchOption } from 'common-v2/components';
import { getWarningMessage, isReviewersHasProjectAccess, convertToSearchOption } from './transducers';
import { BEM_CLASS, SRequestApprovalModal } from './s-request-approval-modal';
import { ReviewerFieldOption } from './types';
import { MAX_REVIEWERS } from './constants';

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

const classes = bem(BEM_CLASS);

export const RequestApprovalModal = React.memo(
  ({
    isOpened,
    className,
    reviewers,
    isLoading,
    isConfidentialProject,
    onConfirm,
    onCancel,
  }: RequestApprovalModalProps) => {
    const [message, setMessage] = useState('');
    const [selectedReviewers, setSelectedReviewers] = useState<ReviewerFieldOption[]>([]);
    const [inputValue, setInputValue] = useState('');
    const [isFormValid, setIsFormValid] = useState(true);
    const [isWarningHidden, setIsWarningHidden] = useState(false);

    const selectOptions = useMemo(() => reviewers.map(convertToSearchOption), [reviewers]);

    const selectedIds = useMemo(() => selectedReviewers.map(reviewer => reviewer.id), [selectedReviewers]);

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

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

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

    const onReviewersSelect = useCallback((options: ReviewerFieldOption[]) => {
      setIsWarningHidden(false);
      setSelectedReviewers(options);
    }, []);

    const onWarningDismiss = useCallback(() => {
      setIsWarningHidden(true);
    }, []);

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

    const handleCancel = useCallback(() => {
      setIsFormValid(true);
      onCancel(selectedIds, message);
    }, [message, onCancel, selectedIds]);

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

    const renderContent = ({ closeModal }: ModalContentProps) => (
      <SRequestApprovalModal className={className} data-selector="request-approval-modal">
        <ModalHeader className={classes('header')} title="Request Approval" closeModal={closeModal} />
        <div className={classes('content')}>
          {!isSelectedReviewersHasProjectAccess && !isWarningHidden && (
            <Alert
              type={ALERT_TYPE.warning}
              size={ALERT_SIZE.small}
              text={warningMessage}
              className={classes('alert')}
              onDismiss={onWarningDismiss}
            />
          )}

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

          <SearchField
            inputValue={inputValue}
            options={selectOptions}
            value={selectedReviewers}
            onChange={onReviewersSelect}
            onInputChange={setInputValue}
            icon="search"
            maxItems={MAX_REVIEWERS}
            error={isFormValid ? undefined : 'Please provide email or name of employee'}
            optionComponent={UserSearchOption}
            popperProps={{ style: { width: '380px' } }}
            listboxClassName={classes('search-field-list')}
            noOptionsClassName={classes('search-field-no-options')}
            placeholder="Search by Name or Email"
            className={classes('search-field', { hasError: !isFormValid })}
            multiple
          />

          <Typography type={TYPOGRAPHY_TYPE.body3} className={classes('textarea-label')}>
            Message (Optional)
          </Typography>

          <Textarea
            value={message}
            data-selector="request-approval-modal-textarea"
            onTextChange={onMessageChange}
            placeholder="Type your message"
            className={classes('textarea-wrapper')}
            inputClassName={classes('textarea')}
            inputProps={{ maxLength: 500 }}
          />
        </div>
        <footer className={classes('footer')}>
          <Button
            className={classes('button', { cancel: true })}
            type={BUTTON_TYPE.secondary}
            theme={THEME.light}
            onClick={handleCancel}
            data-selector="request-approval-modal-cancel-button"
            caption="Cancel"
          />

          <Button
            className={classes('button')}
            theme={THEME.light}
            onClick={onApproveRequest}
            isLoading={isLoading}
            data-selector="request-approval-modal-confirm-button"
            caption="Confirm"
          />
        </footer>
      </SRequestApprovalModal>
    );

    return <Modal isOpened={isOpened} renderContent={renderContent} onClose={handleCancel} />;
  }
);
