import React from 'react';

import { yupResolver } from '@hookform/resolvers/yup';
import { Grid } from '@material-ui/core';
import cx from 'classnames';
import { isAfter, isBefore, isEqual, isValid } from 'date-fns';
import { Controller, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import * as Yup from 'yup';

import { Button, DateTimePicker, Select, TextField } from 'components/common';
import { idOptions, mspmFunctionOptions } from 'constants/ActivityLog';
import {
  DATE_FORMAT_WITH_SECONDS,
  MAX_DATE,
  MIN_DATE,
} from 'constants/manualActions';
import { routePaths } from 'constants/Routes';
import { noSpaces } from 'constants/Validations';
import { useFlagsContext } from 'contexts/FlagsContext';
import { MSPMFunction } from 'models/ActivityLog';
import { ActivityLogSearchFormValues } from 'models/ActivityLogSearchForm';
import { BranchStatus } from 'models/BranchStatus';
import { SetActivityLogSearchFormValues } from 'models/Context';
import { getQueryParams, setQueryParams } from 'utils/ActivityLog';
import './ActivitySearchForm.scss';

export interface ActivitySearchFormProps {
  searchStatus: BranchStatus;
  selectedSearchValues: ActivityLogSearchFormValues;
  setSelectedSearchValues: SetActivityLogSearchFormValues;
}

export const ActivitySearchForm: React.FC<ActivitySearchFormProps> = ({
  searchStatus,
  selectedSearchValues,
  setSelectedSearchValues,
}) => {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const {
    control,
    handleSubmit,
    watch,
    setValue,
    formState: { errors, isValid: isFormValid },
    clearErrors,
  } = useForm({
    resolver: yupResolver(
      Yup.object().shape({
        startTime: Yup.date().required(),
        endTime: Yup.date().required(),
        username: Yup.string(),
        idType: Yup.string(),
        id: Yup.string().matches(
          noSpaces,
          t('validations.cannotContainSpaces'),
        ),
        action: Yup.string(),
      }),
    ),
    mode: 'onChange',
  });
  const { flags } = useFlagsContext();
  const mspmFunctionOptionsWithFlag = [...mspmFunctionOptions];
  if (!flags.BLOCK_SETTLEMENT_FLAG) {
    mspmFunctionOptionsWithFlag.push({
      label: 'Block Settlement',
      value: MSPMFunction.BLOCK_SETTLEMENT,
    });
  }
  if (!flags.SPORTEX_ID_FLAG) {
    mspmFunctionOptionsWithFlag.push({
      label: 'Sportex ID re-map',
      value: MSPMFunction.SPORTEX_REMAPPING,
    });
  }

  const startTimeWatch = watch('startTime');
  const endTimeWatch = watch('endTime');
  const idTypeWatch = watch('idType');

  const loading = searchStatus === BranchStatus.LOADING;

  const onSubmit = (data: ActivityLogSearchFormValues) => {
    setSelectedSearchValues(data);
    const params = setQueryParams(data);

    navigate(`${routePaths.activityLog.resultsPath}?${getQueryParams(params)}`);
  };

  React.useEffect(() => {
    setValue('startTime', selectedSearchValues.startTime);
    setValue('endTime', selectedSearchValues.endTime);
  }, [setValue, selectedSearchValues]);

  return (
    <form
      className="activity-search-form form"
      data-testid="activity-search-form"
      onSubmit={handleSubmit(onSubmit)}
    >
      <Grid container spacing={2}>
        <Grid item xs={3} style={{ minWidth: '16rem' }}>
          <Controller
            name="startTime"
            control={control}
            defaultValue={selectedSearchValues.startTime}
            render={({ onChange, value, name }) => (
              <DateTimePicker
                label={t('form.from')}
                name={name}
                testId="activity-search-form-from-date"
                onChange={onChange}
                value={value}
                maxDate={endTimeWatch ?? MAX_DATE}
                format={DATE_FORMAT_WITH_SECONDS}
                maxDateMessage={t('validations.fromMaxMessage')}
                variant="dialog"
                placeholder={t(
                  'components.activitySearchForm.dateTimePlaceholder',
                )}
              />
            )}
          />
        </Grid>
        <Grid item xs={3} style={{ minWidth: '16rem' }}>
          <Controller
            name="endTime"
            control={control}
            defaultValue={selectedSearchValues.endTime}
            render={({ onChange, value, name }) => (
              <DateTimePicker
                label={t('form.to')}
                name={name}
                testId="activity-search-form-to-date"
                onChange={onChange}
                format={DATE_FORMAT_WITH_SECONDS}
                value={value}
                minDate={startTimeWatch ?? MIN_DATE}
                minDateMessage={t('validations.toMinMessage')}
                variant="dialog"
                placeholder={t(
                  'components.activitySearchForm.dateTimePlaceholder',
                )}
              />
            )}
          />
        </Grid>
        <Grid item xs style={{ flex: '1 0 auto' }}>
          <Controller
            name="username"
            control={control}
            defaultValue={selectedSearchValues.username}
            render={({ onChange, value, name }) => (
              <TextField
                optional
                testId="activity-search-form-username"
                placeholder={t(
                  'components.activitySearchForm.usernamePlaceholder',
                )}
                label={t('components.activitySearchForm.usernameLabel')}
                value={value}
                name={name}
                onChange={onChange}
              />
            )}
          />
        </Grid>
        <Grid item xs={3} style={{ minWidth: '16rem' }}>
          <Controller
            name="idType"
            control={control}
            defaultValue={selectedSearchValues.idType}
            render={({ onChange, value, name }) => (
              <Select
                optional
                testId="activity-search-form-id-type"
                placeholder={t('form.idTypePlaceholder')}
                label={t('form.idTypeLabel')}
                onChange={(event) => {
                  if (event.target.value === '') {
                    setValue('id', '');
                    clearErrors('id');
                  }
                  onChange(event.target.value);
                }}
                value={value}
                name={name}
                options={idOptions}
              />
            )}
          />
        </Grid>
        <Grid item xs={3} style={{ minWidth: '16rem' }}>
          <Controller
            name="id"
            control={control}
            defaultValue={selectedSearchValues.id}
            render={({ onChange, value, name }) => (
              <div className="activity-search-form__id">
                <TextField
                  testId="activity-search-form-id"
                  placeholder={t('form.idPlaceholder')}
                  onChange={onChange}
                  value={value}
                  className={cx({
                    disabled: !idTypeWatch,
                  })}
                  name={name}
                  disabled={!idTypeWatch}
                  error={!!errors.id}
                  helperText={errors.id?.message}
                  label={t('form.idLabel')}
                  optional
                />
              </div>
            )}
          />
        </Grid>
        <Grid item xs style={{ flex: '1 0 auto' }}>
          <Controller
            name="action"
            control={control}
            defaultValue={selectedSearchValues.action}
            render={({ onChange, value, name }) => (
              <Select
                aria-label={`activity-search-form-mspm-function-${name}`}
                testId="activity-search-form-mspm-function"
                onChange={onChange}
                name={name}
                value={value}
                options={mspmFunctionOptionsWithFlag}
                placeholder={t(
                  'components.activitySearchForm.mspmFunctionPlaceholder',
                )}
                label={t('components.activitySearchForm.mspmFunctionLabel')}
                optional
              />
            )}
          />
        </Grid>
        <Grid item xs={12}>
          <Button
            testId="activity-search-form-submit-button"
            className="activity-search-form__submit-button"
            buttonColor="positive"
            type="submit"
            disabled={
              !isValid(startTimeWatch) ||
              !isValid(endTimeWatch) ||
              (!isBefore(startTimeWatch, endTimeWatch) &&
                !isEqual(startTimeWatch, endTimeWatch)) ||
              isBefore(startTimeWatch, new Date(MIN_DATE)) ||
              isAfter(endTimeWatch, new Date(MAX_DATE)) ||
              loading ||
              (!isFormValid && !!idTypeWatch)
            }
            loading={loading}
          >
            {t('common.cta.submit')}
          </Button>
        </Grid>
      </Grid>
    </form>
  );
}; how best to use yup so that I don't have to do this             disabled={
              !isValid(startTimeWatch) ||
              !isValid(endTimeWatch) ||
              (!isBefore(startTimeWatch, endTimeWatch) &&
                !isEqual(startTimeWatch, endTimeWatch)) ||
              isBefore(startTimeWatch, new Date(MIN_DATE)) ||
              isAfter(endTimeWatch, new Date(MAX_DATE)) ||
              loading ||
              (!isFormValid && !!idTypeWatch)
            }