import React, {ReactNode, memo, useMemo, useRef, useState} from 'react';
import {ScrollView, View} from 'react-native';
import {FormProvider, useForm} from 'react-hook-form';
import {ZodTypeAny} from 'zod';
import {IconArrowUp} from '@tabler/icons-react-native';
import {zodResolver} from '@hookform/resolvers/zod';
import {Button, FABButton} from '@components';
import {
  FormCommentableType,
  FormStep,
  FormValues,
  SubmitData,
} from '@components/DynamicForm/interfaces';
import {
  createZodSchemaFromQuestions,
  validateInput,
} from '@components/DynamicForm/utils';
import FormItem from '@components/DynamicForm/components/FormItem';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {StringObject} from '@interfaces/generic';
import {windowDimensions} from '@shared/constants';

import {styles} from './styles';

interface Props {
  data: FormStep[];
  formValues?: FormValues;
  StepHeaderComponent?: ReactNode;
  StepBodyComponent?: (data: FormStep) => ReactNode;
  onSubmitPress?: () => void;
  submitText: string;
  disabled?: boolean;
  FormHeader?: ReactNode;
  buttonIsLoading?: boolean;
  onSubmit?: (data: SubmitData) => void;
}

function FormWrapperScroller({
  data,
  formValues,
  submitText,
  disabled,
  onSubmitPress,
  FormHeader,
  StepHeaderComponent,
  StepBodyComponent,
  buttonIsLoading,
}: Props) {
  const [contentHeight, setContentHeight] = useState(0);
  const paddingBottom = useSafeAreaBottomPadding({bottom: 0});
  const scrollViewRef = useRef<ScrollView>(null);
  const schema = useMemo(
    () => (data ? createZodSchemaFromQuestions(data) : undefined),
    [data],
  );

  const methods = useForm({
    resolver: zodResolver(schema as ZodTypeAny),
    mode: 'onChange',
  });

  const onSubmit = () => {
    let isFormValid = true;
    const formErrors: StringObject = {};

    data.forEach(formStep => {
      const {value, comment} = formValues?.[formStep.name] || {};
      const formError = validateInput(value, formStep.rules);
      const commentError = validateInput(comment, {
        required: formStep.commentable === FormCommentableType.REQUIRED,
      });
      if (formError) {
        formErrors[formStep.name] = formError;
        isFormValid = false;
      } else if (commentError) {
        formErrors[`${formStep.name}-comment`] = commentError;
        isFormValid = false;
      }
    });

    if (isFormValid) {
      onSubmitPress?.();
    }
  };

  const onScrollToTop = () => {
    scrollViewRef.current?.scrollTo({y: 0, animated: true});
  };

  const canScrollToTop = useMemo(() => {
    if (contentHeight > windowDimensions.height - paddingBottom) {
      return true;
    }
    return false;
  }, [contentHeight, paddingBottom]);

  const onContentSizeChange = (_width: number, height: number) => {
    setContentHeight(height);
  };

  return (
    <FormProvider {...methods}>
      <View style={styles.container}>
        <ScrollView
          onContentSizeChange={onContentSizeChange}
          ref={scrollViewRef}
          contentContainerStyle={styles.content}>
          {FormHeader}
          {data.map((formStep, index) => (
            <FormItem
              reviewId={formStep.reviewId}
              key={`${index}`}
              data={formStep}
              HeaderComponent={StepHeaderComponent}
              BodyComponent={StepBodyComponent}
              disabled={disabled}
            />
          ))}
          {canScrollToTop && (
            <View style={styles.fabButton}>
              <FABButton
                text="Volver arriba"
                size="sm"
                Icon={IconArrowUp}
                onPress={onScrollToTop}
              />
            </View>
          )}
        </ScrollView>
        {!disabled && (
          <View style={styles.footer}>
            <Button
              onPress={onSubmit}
              text={submitText}
              isLoading={buttonIsLoading}
            />
          </View>
        )}
      </View>
    </FormProvider>
  );
}

export default memo(FormWrapperScroller);
