import React from 'react';

import { yupResolver } from '@hookform/resolvers/yup';
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, MultiSelect } from 'components/common';
import {
  ConfirmVoidByTimeRangeModal,
  MarketsTableVoidByTimeRange,
} from 'components/manualActions';
import { DATE_FORMAT_WITH_SECONDS, MIN_DATE } from 'constants/manualActions';
import { STATE_SELECTOR_CONFIG } from 'constants/MultiSelect';
import { useManualActionsContext } from 'contexts/ManualActionsContext';
import { usePermissionsContext } from 'contexts/PermissionsContext';
import { BranchStatus } from 'models/BranchStatus';
import {
  VoidByTimeRangeFormValues,
  VoidByTimeRangePayload,
} from 'models/ManualActions';
import { Market } from 'models/Market';
import { State } from 'models/State';
import { isValidDate } from 'utils/Date';

export interface MarketCardProps {
  markets: Market[];
  states: State[];
}

export const MarketCardVoidByTimeRange: React.FC<MarketCardProps> = ({
  markets,
  states,
}) => {
  const { t } = useTranslation();
  const { isAdminUser } = usePermissionsContext();
  const {
    event,
    voidByTimeRange,
    voidByTimeRangeStatus,
    setVoidByTimeRangeStatus,
  } = useManualActionsContext();

  const [isModalOpen, setIsModalOpen] = React.useState(false);
  const [dateStart, setDateStart] = React.useState<string>('');
  const [dateEnd, setDateEnd] = React.useState<string>('');
  const [payload, setPayload] = React.useState<VoidByTimeRangePayload>();
  const [selectedStates, setSelectedStates] = React.useState<string[]>(
    states.map((state: State) => state.id),
  );

  const setMinDate = (date: Date) => {
    if (isValidDate(date)) {
      const minDate = new Date(date);
      minDate.setSeconds(minDate.getSeconds() + 1);
      return new Date(minDate.setMilliseconds(0)).toISOString();
    }
    return date;
  };

  const getDateTime = (date: Date) => new Date(date).setMilliseconds(0);

  const { control, handleSubmit, setValue, watch } =
    useForm<VoidByTimeRangeFormValues>({
      resolver: yupResolver(
        Yup.object().shape({
          fromDate: Yup.date().required(),
          toDate: Yup.date().required(),
          states: Yup.array().required(),
        }),
      ),
    });

  const toDateWatch = watch('toDate');
  const fromDateWatch = watch('fromDate');
  const maxDate = new Date(Date.now());

  React.useEffect(() => {
    setValue('states', selectedStates);
  }, [selectedStates, setValue]);

  const onVoid = async (data: VoidByTimeRangeFormValues) => {
    setIsModalOpen(true);
    setPayload({
      instances: selectedStates,
      event: event?.id as string,
      markets: markets.map(({ id }) => id),
      fromTime: (data.fromDate as Date).getTime(),
      toTime: (data.toDate as Date).getTime(),
    });
    setDateStart((data.fromDate as Date).toUTCString());
    setDateEnd((data.toDate as Date).toUTCString());
  };

  const onSuccess = () => setIsModalOpen(false);
  const onFailure = () => setVoidByTimeRangeStatus(BranchStatus.IDLE);

  const onConfirmVoidByTimeRange = async () => {
    await voidByTimeRange(
      onSuccess,
      onFailure,
      payload as VoidByTimeRangePayload,
    );
    setVoidByTimeRangeStatus(BranchStatus.IDLE);
  };

  return (
    <>
      {voidByTimeRangeStatus !== BranchStatus.FINISHED && (
        <ConfirmVoidByTimeRangeModal
          selectedStates={selectedStates}
          states={states}
          markets={markets}
          open={isModalOpen}
          onClose={() => {
            setIsModalOpen(false);
          }}
          eventName={event?.name as string}
          onConfirm={() => onConfirmVoidByTimeRange()}
          isLoading={voidByTimeRangeStatus === BranchStatus.LOADING}
          dateStart={dateStart}
          dateEnd={dateEnd}
        />
      )}

      <div
        className="market-card market-card--vtr"
        data-testid="markets-card-vtr"
        aria-label={t('accessibility.marketCard')}
      >
        <div className="market-card__header">
          <div className="market-card__header-controls">
            <form
              className="market-card__form"
              onSubmit={handleSubmit(onVoid)}
              data-testid="markets-card-vtr-form"
            >
              <Controller
                control={control}
                name="fromDate"
                defaultValue={null}
                render={({ onChange, value, name }) => (
                  <DateTimePicker
                    label={t('form.from')}
                    testId="markets-card-vtr-form-from-field"
                    name={name}
                    value={fromDateWatch || value}
                    maxDate={toDateWatch || maxDate}
                    maxDateMessage={t('validations.fromMaxMessage')}
                    onChange={(updatedValue) => onChange(updatedValue)}
                    variant="dialog"
                    size="small"
                    format={DATE_FORMAT_WITH_SECONDS}
                  />
                )}
              />
              <Controller
                control={control}
                name="toDate"
                defaultValue={null}
                render={({ onChange, value, name }) => (
                  <DateTimePicker
                    label={t('form.to')}
                    testId="markets-card-vtr-form-to-field"
                    name={name}
                    value={toDateWatch || value}
                    maxDate={maxDate}
                    minDate={setMinDate(fromDateWatch as Date)}
                    minDateMessage={t('validations.toMinMessage')}
                    maxDateMessage={t('validations.toMaxMessage')}
                    onChange={(updatedValue) => onChange(updatedValue)}
                    variant="dialog"
                    size="small"
                    format={DATE_FORMAT_WITH_SECONDS}
                  />
                )}
              />
              <Controller
                control={control}
                name="states"
                defaultValue={null}
                render={() => (
                  <div className="market-card__states">
                    <MultiSelect
                      className="state-selector"
                      label={t('form.states')}
                      options={states.map((state) => ({
                        label: state.name,
                        value: state.id,
                      }))}
                      testId="markets-card-vtr-form-state-selector"
                      onChange={setSelectedStates}
                      value={selectedStates}
                      hasSelectAll
                      selectAllConfig={STATE_SELECTOR_CONFIG}
                      required
                    />
                  </div>
                )}
              />
              <Button
                testId="markets-card-vtr-submit-button"
                type="submit"
                buttonColor="positive"
                disabled={
                  !isAdminUser ||
                  !isBefore(
                    getDateTime(fromDateWatch as Date),
                    getDateTime(toDateWatch as Date),
                  ) ||
                  isAfter(
                    getDateTime(toDateWatch as Date),
                    getDateTime(maxDate),
                  ) ||
                  !isValid(toDateWatch) ||
                  !isValid(fromDateWatch) ||
                  isBefore(fromDateWatch as Date, new Date(MIN_DATE)) ||
                  !selectedStates.length
                }
                className="market-card__submit-button"
              >
                {t('common.cta.void')}
              </Button>
            </form>
          </div>
        </div>
        <MarketsTableVoidByTimeRange markets={markets} />
      </div>
    </>
  );
};
can I use yup to avoid doing this                 disabled={
                  !isAdminUser ||
                  !isBefore(
                    getDateTime(fromDateWatch as Date),
                    getDateTime(toDateWatch as Date),
                  ) ||
                  isAfter(
                    getDateTime(toDateWatch as Date),
                    getDateTime(maxDate),
                  ) ||
                  !isValid(toDateWatch) ||
                  !isValid(fromDateWatch) ||
                  isBefore(fromDateWatch as Date, new Date(MIN_DATE)) ||
                  !selectedStates.length
                }?