import React from 'react';

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

import {
  Button,
  DateTimePicker,
  Label,
  RadioGroup,
  Select,
  TagSelector,
} from 'components/common';
import { MAX_DATE, MIN_DATE, eventDateOptions } from 'constants/manualActions';
import { useFlagsContext } from 'contexts/FlagsContext';
import {
  blockSettlementDefault,
  useManualActionsContext,
} from 'contexts/ManualActionsContext';
import { BranchStatus } from 'models/BranchStatus';
import { Competition, ListCompetitions } from 'models/Competition';
import { ListEvents } from 'models/Context';
import {
  EventSearchCheckBoxesOptions,
  EventSearchFormValues,
} from 'models/EventSearchForm';
import { FeatureFlags } from 'models/FeatureFlags';
import { Sport } from 'models/Sport';
import { getDatesFromRange } from 'utils/Date';

export interface EventSearchFormProps {
  sports: Sport[];
  competitions: Competition[];
  selectedSearchValues: EventSearchFormValues;
  listCompetitions: ListCompetitions;
  listCompetitionsStatus: BranchStatus;
  listEvents: ListEvents;
  listEventsStatus: BranchStatus;
  rowsPerPage: number;
  disableEventStatus: boolean;
}

const showBlockSettlement = (flags: FeatureFlags): boolean =>
  !flags.BLOCK_SETTLEMENT_FLAG;

const checkBoxes: EventSearchCheckBoxesOptions = [
  {
    labelName: 'resettlementBlockedEvents',
    formName: 'eventStatusBlocked',
  },
  {
    labelName: 'settlementBlockedEvents',
    formName: 'eventStatus',
  },
  {
    labelName: 'unsettledEvents',
    formName: 'isFullyResulted',
  },
];

export const EventSearchForm: React.FC<EventSearchFormProps> = ({
  sports,
  competitions,
  selectedSearchValues,
  listCompetitions,
  listCompetitionsStatus,
  listEvents,
  listEventsStatus,
  rowsPerPage,
  disableEventStatus,
}) => {
  const { t } = useTranslation();
  const { flags } = useFlagsContext();

  const { setBlockSettlementPayload } = useManualActionsContext();

  const { control, handleSubmit, setValue, watch } =
    useForm<EventSearchFormValues>({
      resolver: yupResolver(
        Yup.object().shape({
          sport: Yup.string().required(),
          competitions: Yup.array().required(),
          fromDate: Yup.date().required(),
          toDate: Yup.date().required(),
          eventDate: Yup.string().nullable(),
          eventStatusBlocked: Yup.boolean().required(),
          isFullyResulted: Yup.boolean(),
          eventStatus: Yup.boolean(),
        }),
      ),
    });

  const eventDateWatch = watch('eventDate');
  const sportWatch = watch('sport');
  const competitionsWatch = watch('competitions');
  const toDateWatch = watch('toDate');
  const fromDateWatch = watch('fromDate');

  React.useEffect(() => {
    if (typeof eventDateWatch !== 'undefined' && eventDateWatch) {
      const { fromDate, toDate } = getDatesFromRange(
        new Date(Date.now()),
        eventDateWatch,
      );

      setValue('fromDate', fromDate);
      setValue('toDate', toDate);

      selectedSearchValues.fromDate = fromDate;
      selectedSearchValues.toDate = toDate;
    } else if (typeof eventDateWatch === 'undefined') {
      setValue('fromDate', selectedSearchValues.fromDate);
      setValue('toDate', selectedSearchValues.toDate);
    }
  }, [eventDateWatch, selectedSearchValues, setValue]);

  React.useEffect(() => {
    sportWatch && listCompetitions(+sportWatch);
  }, [sportWatch, listCompetitions]);

  const onSubmit = async (data: EventSearchFormValues) => {
    await listEvents(data, 0, rowsPerPage);
    setBlockSettlementPayload(blockSettlementDefault);
  };

  const eventSearchFormBlockedStyles = cx(
    'event-search-form__blocked-content',
    {
      [`disabled`]: disableEventStatus,
    },
  );

  return (
    <form
      className="event-search-form"
      onSubmit={handleSubmit(onSubmit)}
      data-testid="event-search-form"
    >
      <Controller
        name="sport"
        control={control}
        defaultValue={selectedSearchValues.sport}
        render={({ onChange, value, name }) => (
          <Select
            label={t('form.sport')}
            className="event-search-form__sport-select"
            testId="event-search-form-sport-select"
            placeholder={t('form.sportPlaceholder')}
            options={sports.map((sport) => {
              return { label: sport.name, value: sport.id.toString() };
            })}
            name={name}
            value={value}
            onChange={(event) => {
              setValue('competitions', []);
              onChange(event);
            }}
          />
        )}
      />
      <Controller
        name="competitions"
        control={control}
        defaultValue={selectedSearchValues.competitions}
        render={({ onChange, value, name }) => (
          <TagSelector
            label={t('form.competition')}
            className="event-search-form__competition-select"
            options={competitions.map((competition) => {
              return {
                label: competition.name,
                value: competition.id,
              };
            })}
            placeholder={t('form.competitionPlaceholder')}
            testId="event-search-form-competition-select"
            onChange={onChange}
            disabled={!sportWatch}
            loading={listCompetitionsStatus === BranchStatus.LOADING}
            value={value}
            name={name}
          />
        )}
      />
      <div className="event-search-form__blocked-container">
        {!showBlockSettlement(flags) ? (
          <Controller
            name="eventStatusBlocked"
            control={control}
            defaultValue={selectedSearchValues.eventStatusBlocked}
            render={({ value, name, onChange }) => (
              <>
                <Label
                  label={t('form.eventStatus')}
                  className="event-search-form__event-status-label"
                  id="eventStatus"
                  testId="event-status-label"
                />
                <div className={eventSearchFormBlockedStyles}>
                  <Checkbox
                    checked={!!value}
                    disabled={disableEventStatus}
                    name={name}
                    className="event-search-form__blocked-checkbox"
                    data-testid="event-search-form-blocked-checkbox"
                    color="primary"
                    onChange={(event) => {
                      onChange(event.target.checked);
                    }}
                  />
                  <p className="event-search-form__blocked-label">
                    {t('form.blockedLabel')}
                  </p>
                </div>
              </>
            )}
          />
        ) : (
          <>
            <Label testId="event-status-label" label={t('form.eventStatus')} />
            <FormGroup>
              {checkBoxes.map(({ labelName, formName }, index) => (
                <FormControlLabel
                  label={t(`form.${labelName}`)}
                  key={labelName}
                  control={
                    <Controller
                      name={formName}
                      control={control}
                      defaultValue={!!selectedSearchValues[formName]}
                      render={({ onChange, value }) => (
                        <Checkbox
                          checked={!!value}
                          name={formName}
                          className="event-search-form__event-status-checkbox"
                          data-testid={
                            index === 0
                              ? 'event-search-form-blocked-checkbox'
                              : undefined
                          }
                          color="primary"
                          onChange={(event) => onChange(event.target.checked)}
                        />
                      )}
                    />
                  }
                />
              ))}
            </FormGroup>
          </>
        )}
      </div>
      <div className="event-search-form__date-container">
        <Controller
          control={control}
          name="eventDate"
          defaultValue={selectedSearchValues.eventDate}
          render={({ onChange, value, name }) => (
            <RadioGroup
              label={t('form.eventDate')}
              onChangeRadio={onChange}
              testId="event-search-form-event-date"
              options={eventDateOptions}
              name={name}
              value={value}
            />
          )}
        />
        <Controller
          control={control}
          name="fromDate"
          defaultValue={selectedSearchValues.fromDate}
          render={({ onChange, value, name }) => (
            <DateTimePicker
              label={t('form.from')}
              testId="event-search-form-from-date"
              name={name}
              value={fromDateWatch || value}
              maxDate={toDateWatch}
              maxDateMessage={t('validations.fromMaxMessage')}
              onChange={(updatedDate) => {
                onChange(updatedDate);
                setValue('eventDate', null);
              }}
              variant="dialog"
            />
          )}
        />
        <Controller
          control={control}
          name="toDate"
          defaultValue={selectedSearchValues.toDate}
          render={({ onChange, value, name }) => (
            <DateTimePicker
              label={t('form.to')}
              testId="event-search-form-to-date"
              name={name}
              value={toDateWatch || value}
              minDate={fromDateWatch}
              minDateMessage={t('validations.toMinMessage')}
              onChange={(newValue) => {
                onChange(newValue);
                setValue('eventDate', null);
              }}
              variant="dialog"
            />
          )}
        />
      </div>
      <Button
        testId="event-search-form-submit-button"
        type="submit"
        buttonColor="positive"
        disabled={
          !sportWatch ||
          !competitionsWatch?.length ||
          !isValid(toDateWatch) ||
          !isValid(fromDateWatch) ||
          !isBefore(fromDateWatch as Date, toDateWatch as Date) ||
          isBefore(fromDateWatch as Date, new Date(MIN_DATE)) ||
          isAfter(toDateWatch as Date, new Date(MAX_DATE)) ||
          listEventsStatus === BranchStatus.LOADING
        }
        className="event-search-form__submit-button"
        loading={listEventsStatus === BranchStatus.LOADING}
      >
        {t('common.cta.submit')}
      </Button>
    </form>
  );
};
can I make this better so that I don't have to do this         disabled={
          !sportWatch ||
          !competitionsWatch?.length ||
          !isValid(toDateWatch) ||
          !isValid(fromDateWatch) ||
          !isBefore(fromDateWatch as Date, toDateWatch as Date) ||
          isBefore(fromDateWatch as Date, new Date(MIN_DATE)) ||
          isAfter(toDateWatch as Date, new Date(MAX_DATE)) ||
          listEventsStatus === BranchStatus.LOADING
        }