import { useMutation, useProgramId, useQuery, useUserIdentity, } from "@saasquatch/component-boilerplate";
import { useCallback, useEffect, useRef, useState, } from "@saasquatch/universal-hooks";
import { gql } from "graphql-request";
import jsonpointer from "jsonpointer";
import { AsYouType } from "libphonenumber-js";
import { useLeadFormState } from "./useLeadFormState";
const SUBMIT_LEAD = gql `
  mutation submitForm($formSubmissionInput: FormSubmissionInput!) {
    submitForm(formSubmissionInput: $formSubmissionInput) {
      success
    }
  }
`;
const GET_USER_DETAILS = gql `
  query getUser($programId: ID) {
    viewer {
      ... on User {
        referralCode(programId: $programId)
      }
    }
  }
`;
export function useLeadForm(props) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
  const formRef = useRef(null);
  const { leadFormState, setLeadFormState } = useLeadFormState({});
  const programId = useProgramId();
  const user = useUserIdentity();
  const { data: userDetails } = useQuery(GET_USER_DETAILS, { programId }, !(user === null || user === void 0 ? void 0 : user.jwt) || !programId);
  const [submitLead, { loading, errors, data }] = useMutation(SUBMIT_LEAD);
  const [success, setSuccess] = useState(false);
  useEffect(() => {
    if (!formRef.current)
      return;
    const form = formRef.current;
    form.addEventListener("sl-input", inputFunction);
    return () => {
      form.removeEventListener("sl-input", inputFunction);
    };
  }, [formRef.current]);
  const submit = async (event) => {
    var _a;
    let formControls = event.target.getFormControls();
    let formData = {};
    let validationErrors = {};
    formControls === null || formControls === void 0 ? void 0 : formControls.forEach((control) => {
      if (!control.name)
        return;
      const key = control.name;
      const value = control.value;
      jsonpointer.set(formData, key, value);
      // required validation
      if (control.required && !value) {
        jsonpointer.set(validationErrors, key, props.requiredFieldErrorMessage);
      }
      // custom validation
      if (typeof control.validationError === "function") {
        const validate = control.validationError;
        const validationError = validate({ control, key, value });
        if (validationError)
          jsonpointer.set(validationErrors, key, validationError);
      }
    });
    if (Object.keys(validationErrors).length) {
      setLeadFormState({ loading: false, error: "", validationErrors });
      // early return for validation errors
      return;
    }
    setLeadFormState({
      loading: true,
      error: "",
      validationErrors: {},
    });
    const variables = {
      key: props.formKey,
      formData,
    };
    try {
      const result = await submitLead({ formSubmissionInput: variables });
      if (result instanceof Error) {
        throw result;
      }
      setLeadFormState({
        loading: false,
        error: "",
        validationErrors: {},
      });
      if ((_a = result === null || result === void 0 ? void 0 : result.submitForm) === null || _a === void 0 ? void 0 : _a.success) {
        setSuccess(true);
      }
    }
    catch (error) {
      setLeadFormState({
        loading: false,
        error: props.networkErrorMessage,
        validationErrors: {},
      });
    }
  };
  const inputFunction = useCallback((e) => {
    var _a, _b;
    const name = (_b = (_a = e.target) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.toLowerCase();
    if (name !== "tel")
      return;
    const asYouType = new AsYouType("US");
    e.target.value = asYouType.input(e.target.value);
  }, []);
  function resetForm() {
    var _a, _b;
    setLeadFormState({
      loading: false,
      error: "",
      validationErrors: {},
    });
    (_b = (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.getFormControls()) === null || _b === void 0 ? void 0 : _b.forEach((c) => {
      var _a;
      if (((_a = c.input) === null || _a === void 0 ? void 0 : _a.type) === "checkbox") {
        c.checked = false;
        c.value = false;
      }
      else {
        c.value = "";
      }
    });
    setSuccess(false);
  }
  let errorMessage = "";
  if ((_a = errors === null || errors === void 0 ? void 0 : errors.response) === null || _a === void 0 ? void 0 : _a["error"]) {
    errorMessage = props.networkErrorMessage;
  }
  else if ((errors === null || errors === void 0 ? void 0 : errors.message) && !((_b = errors === null || errors === void 0 ? void 0 : errors.response) === null || _b === void 0 ? void 0 : _b.errors.length)) {
    errorMessage = props.networkErrorMessage;
  }
  else {
    errorMessage =
      ((_f = (_e = (_d = (_c = errors === null || errors === void 0 ? void 0 : errors.response) === null || _c === void 0 ? void 0 : _c.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.extensions) === null || _f === void 0 ? void 0 : _f.message) || ((_j = (_h = (_g = errors === null || errors === void 0 ? void 0 : errors.response) === null || _g === void 0 ? void 0 : _g.errors) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.message) || (leadFormState === null || leadFormState === void 0 ? void 0 : leadFormState.error);
  }
  return {
    states: {
      loading,
      error: errorMessage,
      success,
      leadFormState,
      referralCode: ((_k = userDetails === null || userDetails === void 0 ? void 0 : userDetails.viewer) === null || _k === void 0 ? void 0 : _k.referralCode) || "",
    },
    callbacks: {
      submit,
      inputFunction,
      resetForm,
    },
    refs: {
      formRef,
    },
  };
}
