import { useMemo, useCallback } from 'react';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';

import { Box, Button, Text } from 'components/common';
import { ErrorBoundary } from 'components/ErrorBoundary';
import { FilterGroupData, FilterGroups } from './';

import {
  getDefaultState,
  getInitialState,
  convertToFiltersInput,
} from 'components/filters/utils';

import { call } from 'utils/call';

export type HandleSubmit = (
  input: ReturnType<typeof convertToFiltersInput>,
  data: Record<string, string[]>
) => void;

export interface FiltersFormProps {
  filters: FilterGroupData[];
  initialState: {
    id: string;
    type: string;
    values: string[];
  }[];
  onSubmit?: HandleSubmit;
  onReset?: () => void;
  loading: boolean;
}

export const FiltersForm = ({
  filters,
  initialState: initial,
  onSubmit,
  onReset,
  loading,
}: FiltersFormProps) => {
  const defaultState = useMemo(() => getDefaultState(filters), [filters]);
  const initialState = useMemo(() => getInitialState(initial), [initial]);

  const defaultValues = initial ? initialState : defaultState;

  const methods = useForm({ defaultValues });
  const { formState, reset, handleSubmit } = methods;

  const apply: SubmitHandler<Record<string, string[]>> = useCallback(
    (data) => {
      const input = convertToFiltersInput(data);
      call(onSubmit, input, data);
    },
    [onSubmit]
  );

  const resetForm = useCallback(() => {
    reset(defaultState);
    call(onReset);
  }, [reset, defaultState, onReset]);

  if (Array.isArray(filters) && filters.length > 0) {
    return (
      <ErrorBoundary>
        <FormProvider {...methods}>
          <Box display="flex" column spacingY={2}>
            <Box display="flex" column spacingY={4}>
              <FilterGroups items={filters} />
            </Box>
            <Box
              className="bg-white"
              position="sticky"
              bottom={0}
              paddingX={3}
              paddingY={4}
              spacingY={2}
            >
              <Button
                onClick={handleSubmit(apply)}
                disabled={!formState.isDirty || loading}
                color="blue"
                block
              >
                Apply filters
              </Button>

              {formState.isDirty && (
                <Box className="tac">
                  <span className="fz14 cup hoverText" onClick={resetForm}>
                    Reset
                  </span>
                </Box>
              )}
            </Box>
          </Box>
        </FormProvider>
      </ErrorBoundary>
    );
  } else {
    return (
      <Box padding={3}>
        <Text size="s">Nothing to filter</Text>
      </Box>
    );
  }
};
