import { ref, nextTick } from "vue";

export function useSubmitHandler(options = {}) {
  const { onSuccess, onError, formRef, scrollFn, containerRef } = options;

  const loading = ref(false);
  const validationErrors = ref({});

  const getFormRefs = () => {
    const refs = formRef?.value;
    if (!refs) return [];
    return Array.isArray(refs) ? refs : [refs];
  };

  const scrollToFirstError = async () => {
    if (!formRef?.value || !scrollFn) return;
    await nextTick();

    const refsToSearch = getFormRefs();

    for (const ref of refsToSearch) {
      if (!ref) continue;
      const components = ref.getValidationComponents();
      if (!components) continue;

      const firstErrorComponent = components.find((c) => c.hasError);

      if (firstErrorComponent) {
        const container = containerRef?.value || containerRef;
        firstErrorComponent.focus();
        scrollFn(firstErrorComponent, container);
        return;
      }
    }
  };

  const execute = async (apiCallThunk) => {
    loading.value = true;
    validationErrors.value = {};

    let allValid = true;
    const refsToValidate = getFormRefs();

    if (refsToValidate.length > 0) {
      for (const ref of refsToValidate) {
        if (ref) {
          const success = await ref.validate(true);
          if (!success) {
            allValid = false;
          }
        }
      }
    }

    if (!allValid) {
      loading.value = false;
      await scrollToFirstError();
      throw new Error("Frontend validation failed.");
    }

    try {
      const response = await apiCallThunk();
      if (typeof onSuccess === "function") {
        await onSuccess(response);
      } else {
        return response;
      }
    } catch (error) {
      await handleError(error);
    } finally {
      loading.value = false;
    }
  };

  const handleError = async (error) => {
    if (error?.response?.status === 422) {
      const errors = error.response.data.errors || {};
      for (const key in errors) {
        const message = errors[key][0];
        validationErrors.value[key] = message;
      }
      await scrollToFirstError();
    }

    await nextTick();
    if (typeof onError === "function") {
      await onError(error);
    } else {
      throw error;
    }
  };

  return {
    loading,
    validationErrors,
    execute,
  };
}
