import {
  type FieldError,
  type FieldErrors,
  type Resolver,
} from 'react-hook-form';

import { set } from 'lodash-es';
import { mixed, object, ValidationError } from 'yup';

import { type SurveyFormValues } from '../../types';

type ToFormDataParams<TValue> = {
  value: TValue;
  optionsLength?: number | undefined;
};

export const toMultiChoiceFormData = ({
  value,
  optionsLength = 0,
}: ToFormDataParams<number[]>) =>
  value.reduce(
    (acc, current) => {
      acc[current] = true;
      return acc;
    },
    Array.from({ length: optionsLength }, () => false),
  );

export const toMultiChoiceServerData = (value: boolean[]) =>
  value.reduce((acc, current, index) => {
    if (current) {
      acc.push(index);
    }
    return acc;
  }, [] as number[]);

export const toUniqChoiceFormData = ({
  value,
  optionsLength = 0,
}: ToFormDataParams<number>) => {
  const formData = Array.from({ length: optionsLength }, () => false);
  formData[value] = true;
  return formData;
};

export const toUniqChoiceServerData = (value: boolean[]) =>
  value.findIndex(Boolean);

const questionFormSchema = object().shape({
  answer: mixed().test('required', '', value => {
    if (typeof value === 'string') {
      return value.trim().length > 0;
    }

    if (typeof value === 'number') {
      return value !== null && value !== undefined;
    }

    if (
      Array.isArray(value) &&
      value.length > 0 &&
      typeof value[0] === 'boolean'
    ) {
      return value.some(Boolean);
    }

    return false;
  }),
});

export const formResolver: Resolver<SurveyFormValues> = values => {
  try {
    questionFormSchema.validateSync(values, {
      abortEarly: false,
    });

    return {
      values,
      errors: {},
    };
  } catch (validationError) {
    console.error({ validationError });
    if (validationError instanceof ValidationError) {
      const errors: FieldErrors<SurveyFormValues> = {};
      validationError.inner.forEach(error => {
        if (error.path) {
          set(errors, error.path, {
            type: error.type || 'validation',
            message: error.message,
          } as FieldError);
        }
      });
      return {
        values: {},
        errors,
      };
    }
    return {
      values: {},
      errors: {},
    };
  }
};
