import { createContext, type ReactNode } from 'react';
import { FormProvider } from 'react-hook-form';

import { type UseDynamicFormReturn } from '../hooks/useDynamicForm';
import { type DynamicFormProgressionBase } from '../types';

export type DynamicFormContextProviderProps<
  T extends DynamicFormProgressionBase = DynamicFormProgressionBase,
> = UseDynamicFormReturn<T> & {
  children: ReactNode;
};

// Cannot use Omit as TypeScript is not able to infer the type of the context
export const DynamicFormContext = createContext<
  Pick<
    UseDynamicFormReturn,
    | 'isInitializingForm'
    | 'formResponse'
    | 'isLoading'
    | 'formTitle'
    | 'isFrozen'
    | 'shouldShowFormBody'
    | 'shouldShowFormFooter'
    | 'shouldShowFormSuccess'
    | 'submitSection'
    | 'changeStep'
    | 'getFirstErrorIndex'
    | 'setFormResponse'
    | 'setFormTitle'
    | 'setIsFrozen'
    | 'setCanShowSuccessScreen'
    | 'setStartTime'
  > & {
    updateProgressionMutation:
      | UseDynamicFormReturn['updateProgressionMutation']
      | null;
    form: UseDynamicFormReturn['form'] | null;
  }
>({
  isInitializingForm: false,
  formResponse: null,
  isLoading: false,
  updateProgressionMutation: null,
  form: null,
  submitSection: () => {},
  changeStep: () => {},
  getFirstErrorIndex: () => 0,
  isFrozen: false,
  setFormResponse: () => {},
  setFormTitle: () => {},
  setIsFrozen: () => {},
  setCanShowSuccessScreen: () => {},
  setStartTime: () => {},
  shouldShowFormBody: false,
  shouldShowFormFooter: false,
  shouldShowFormSuccess: false,
  formTitle: '',
});

const DynamicFormContextProvider = <
  T extends DynamicFormProgressionBase = DynamicFormProgressionBase,
>({
  children,
  ...props
}: DynamicFormContextProviderProps<T>) => {
  const { formResponse, form } = props;
  return (
    <FormProvider
      {...form}
      key={formResponse?.currentSection}
    >
      <DynamicFormContext.Provider value={props as any}>
        {children}
      </DynamicFormContext.Provider>
    </FormProvider>
  );
};

export default DynamicFormContextProvider;
