import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { bem } from 'utils/bem';
import { SProjectForm, BEM_CLASS } from './s-project-form';
import { Artist, ArtistSearch, ProjectDetails } from 'backend-api/models';
import { Icon, ICON_SIZE, Typography, TYPOGRAPHY_TYPE, Tooltip, TOOLTIP_PLACEMENT } from 'gdb-web-shared-components';
import { ArtistsGrid, DateRangeField, InputField } from './components';
import { projectNameValidation } from './components/input-field/transducers';
import { Prompt } from 'react-router';
import { useFormikContext } from 'formik';
import { ProjectFormValues } from 'project-v2/types';
import { getFieldsWithDiffValues, getPrimaryAndFeaturedArtists } from 'project-v2/transducers';
import { useDispatch } from 'react-redux';
import { openEditArtistsModal } from 'project-v2/actions';
import { EditArtistsModalContainer } from 'project-v2/containers/edit-artists-modal-container';

interface ProjectFormProps {
  project: ProjectDetails;
  isEditing: boolean;
  shouldIgnoreUnsavedChanges: boolean;
  dateFormat: string;
  onEditFeaturedArtists(artists: Artist[]): void;
  className?: string;
}

const classes = bem(BEM_CLASS);

export const ProjectForm = React.memo(
  ({ project, isEditing, shouldIgnoreUnsavedChanges, dateFormat, className }: ProjectFormProps) => {
    const [tooltipText, setTooltipText] = useState('Copy');
    const dispatch = useDispatch();
    const { values, handleReset, initialValues, validateForm, setFieldValue } = useFormikContext<ProjectFormValues>();

    const isFormChanged = useMemo(() => {
      const changedValues = getFieldsWithDiffValues(initialValues, values);
      return changedValues.length > 0;
    }, [values, initialValues]);

    const copyGrasId = useCallback(() => {
      if (!project.grasData) {
        return;
      }

      navigator.clipboard.writeText(project.grasData.id).then(() => {
        setTooltipText('Copied');
      });
    }, [project.grasData]);

    const resetTooltipText = useCallback(() => {
      setTooltipText('Copy');
    }, []);

    const shouldInterruptPageReload = (isFormChanged || isEditing) && !shouldIgnoreUnsavedChanges;

    const { primaryArtists, featuredArtists } = useMemo(() => getPrimaryAndFeaturedArtists(values.artists), [
      values.artists,
    ]);

    const editFeaturedArtists = useCallback(() => {
      dispatch(openEditArtistsModal({ selectedArtists: featuredArtists }));
    }, [dispatch, featuredArtists]);

    const onFeaturedArtistsUpdated = useCallback(
      (artists: ArtistSearch[]) => {
        const featuredArtists: Artist[] = artists.map(artist => ({ ...artist, type: 'Featured', isPRS: undefined }));
        const allArtist = [...primaryArtists, ...featuredArtists];
        setFieldValue('artists', allArtist);
      },
      [primaryArtists, setFieldValue]
    );

    useEffect(() => {
      validateForm();

      if (!isEditing) {
        handleReset();
      }
    }, [validateForm, handleReset, isEditing]);

    useEffect(() => {
      const handleBeforeUnloadEvent = (event: BeforeUnloadEvent) => {
        if (shouldInterruptPageReload) {
          event.preventDefault();
          event.returnValue = '';
        }
      };

      window.addEventListener('beforeunload', handleBeforeUnloadEvent);

      return () => {
        window.removeEventListener('beforeunload', handleBeforeUnloadEvent);
      };
    }, [shouldInterruptPageReload]);

    return (
      <SProjectForm className={className}>
        <div className={classes('container')}>
          <Typography type={TYPOGRAPHY_TYPE.heading2}>General Information</Typography>
          <div className={classes('form')}>
            <div className={classes('field')} data-selector="project-form-name">
              <InputField
                name="name"
                label="Project Name"
                validate={projectNameValidation}
                className={classes('name-input')}
              />
            </div>
            <div className={classes('field')}>
              <div className={classes('grass-id-container')} data-selector="project-form-gras-id">
                <InputField name="grassId" disabled label="GRAS ID" className={classes('grass-id-input')} />

                <div className={classes('copy-wrapper')}>
                  <Tooltip tooltip={tooltipText} placement={TOOLTIP_PLACEMENT.Top} onClose={resetTooltipText}>
                    <button
                      className={classes('copy')}
                      type="button"
                      onClick={copyGrasId}
                      data-selector="project-form-gras-id-copy-button"
                    >
                      <Icon className={classes('icon')} name="copy-outlined" size={ICON_SIZE.small} />
                    </button>
                  </Tooltip>
                </div>
              </div>
            </div>
            <div className={classes('field')} data-selector="project-form-dates">
              <Typography type={TYPOGRAPHY_TYPE.body3}>Project Dates</Typography>
              <DateRangeField name="dates" dateFormat={dateFormat} />
            </div>
            <div className={classes('separator')} />
            <ArtistsGrid title="Primary Artists" artists={primaryArtists} />
            <div className={classes('separator')} />
            <ArtistsGrid
              title="Featured Artists"
              artists={featuredArtists}
              onEdit={editFeaturedArtists}
              emptyText="You don’t have any featured artists."
            />
          </div>
        </div>
        <Prompt when={shouldInterruptPageReload} message="Changes that you made may not be saved." />
        <EditArtistsModalContainer onArtistsUpdated={onFeaturedArtistsUpdated} />
      </SProjectForm>
    );
  }
);
