import jsonpointer from "jsonpointer";
import { useCallback, useEffect, useRef } from "@saasquatch/universal-hooks";
import { navigation, useLocale, useQuery, useRegisterViaRegistrationFormMutation, } from "@saasquatch/component-boilerplate";
import { AsYouType } from "libphonenumber-js";
import { gql } from "graphql-request";
import { useRegistrationFormState, } from "./useRegistrationFormState";
const RegistrationFormQuery = gql `
  query RegistrationFormQuery($key: String!) {
    form(key: $key) {
      key
      type
      initialData {
        initialData
        isEnabled
        isEnabledErrorMessage
      }
    }
  }
`;
export function usePortalRegistrationForm(props) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
  const formRef = useRef(null);
  const locale = useLocale();
  const { registrationFormState, setRegistrationFormState } = useRegistrationFormState({});
  const [request, { loading, errors, data, formError }] = useRegisterViaRegistrationFormMutation();
  const queryResponse = useQuery(RegistrationFormQuery, { key: props.formKey });
  const formLoading = loading || queryResponse.loading;
  useEffect(() => {
    var _a, _b, _c;
    const initialData = (_a = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _a === void 0 ? void 0 : _a.form.initialData.initialData;
    const disabled = ((_b = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _b === void 0 ? void 0 : _b.form.initialData.isEnabled) === false;
    const disabledMessage = ((_c = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _c === void 0 ? void 0 : _c.form.initialData.isEnabledErrorMessage) ||
      props.formDisabledErrorMessage;
    const formState = {
      loading: formLoading,
      disabled,
      disabledMessage,
      initialData,
    };
    setRegistrationFormState(formState);
  }, [(_a = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _a === void 0 ? void 0 : _a.form.initialData]);
  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, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
    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;
      // control.value = initialData[key] || 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 ((props.confirmPassword || formData.confirmPassword) &&
      formData.password !== formData.confirmPassword) {
      validationErrors = {
        ...validationErrors,
        confirmPassword: props.passwordMismatchErrorMessage,
      };
    }
    if (Object.keys(validationErrors).length) {
      // early return for validation errors
      setRegistrationFormState({
        ...registrationFormState,
        loading: false,
        error: "",
        validationErrors,
      });
      return;
    }
    setRegistrationFormState({
      ...registrationFormState,
      loading: true,
      error: "",
      validationErrors: {},
    });
    const { email, password } = formData;
    delete formData.email;
    delete formData.password;
    delete formData.confirmPassword;
    const redirectPath = props.redirectPath;
    const _googleOAuthIdToken = registrationFormState._googleOAuthIdToken;
    const variables = {
      key: props.formKey,
      formData: {
        ...(_googleOAuthIdToken ? { _googleOAuthIdToken } : {}),
        locale,
        email,
        password,
        redirectPath,
        ...formData,
      },
    };
    try {
      const result = await request(variables);
      if (result instanceof Error) {
        throw result;
      }
      setRegistrationFormState({
        ...registrationFormState,
        loading: false,
        error: "",
        validationErrors: {},
      });
      const managedIdentityResponse = (_a = result.submitForm) === null || _a === void 0 ? void 0 : _a.results.find((result) => { var _a; return ((_a = result === null || result === void 0 ? void 0 : result.formHandler) === null || _a === void 0 ? void 0 : _a.namespace) === "identity"; });
      if (managedIdentityResponse &&
        managedIdentityResponse.result.results.length &&
        managedIdentityResponse.result.results[0].success &&
        managedIdentityResponse.result.results[0].data.token) {
        navigation.push(props.nextPage);
      }
      else if (
      // check for blocked email error response
      ((_b = result.submitForm) === null || _b === void 0 ? void 0 : _b.results.length) === 1 &&
        ((_f = (_e = (_d = (_c = result.submitForm) === null || _c === void 0 ? void 0 : _c.results[0]) === null || _d === void 0 ? void 0 : _d.result) === null || _e === void 0 ? void 0 : _e.results) === null || _f === void 0 ? void 0 : _f.length) === 1 &&
        ((_l = (_k = (_j = (_h = (_g = result.submitForm) === null || _g === void 0 ? void 0 : _g.results[0]) === null || _h === void 0 ? void 0 : _h.result) === null || _j === void 0 ? void 0 : _j.results) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.success) ===
          false && ((_s = (_r = (_q = (_p = (_o = (_m = result.submitForm) === null || _m === void 0 ? void 0 : _m.results[0]) === null || _o === void 0 ? void 0 : _o.result) === null || _p === void 0 ? void 0 : _p.results) === null || _q === void 0 ? void 0 : _q[0]) === null || _r === void 0 ? void 0 : _r.message) === null || _s === void 0 ? void 0 : _s.startsWith("Blocked email"))) {
        setRegistrationFormState({
          ...registrationFormState,
          loading: false,
          error: "",
          validationErrors: {
            email: props.invalidEmailErrorMessage,
          },
        });
      }
    }
    catch (error) {
      // check for invalid email
      if ((_t = error === null || error === void 0 ? void 0 : error.message) === null || _t === void 0 ? void 0 : _t.includes("is not a valid email address")) {
        setRegistrationFormState({
          ...registrationFormState,
          loading: false,
          error: "",
          validationErrors: { email: props.invalidEmailErrorMessage },
        });
      }
      else {
        setRegistrationFormState({
          ...registrationFormState,
          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);
  }, []);
  let errorMessage = "";
  if (((_b = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _b === void 0 ? void 0 : _b.form.initialData.isEnabled) === false) {
    errorMessage =
      ((_c = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.data) === null || _c === void 0 ? void 0 : _c.form.initialData.isEnabledErrorMessage) ||
        props.formDisabledErrorMessage;
  }
  else if ((_d = errors === null || errors === void 0 ? void 0 : errors.response) === null || _d === void 0 ? void 0 : _d["error"]) {
    errorMessage = props.networkErrorMessage;
  }
  else if ((errors === null || errors === void 0 ? void 0 : errors.message) && !((_e = errors === null || errors === void 0 ? void 0 : errors.response) === null || _e === void 0 ? void 0 : _e.errors.length)) {
    errorMessage = props.networkErrorMessage;
  }
  else {
    errorMessage =
      formError || ((_j = (_h = (_g = (_f = queryResponse === null || queryResponse === void 0 ? void 0 : queryResponse.errors) === null || _f === void 0 ? void 0 : _f.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) || (registrationFormState === null || registrationFormState === void 0 ? void 0 : registrationFormState.error);
  }
  return {
    states: {
      loading: loading || queryResponse.loading,
      error: errorMessage,
      registrationFormState,
      confirmPassword: props.confirmPassword,
      hideInputs: props.hideInputs,
      loginPath: props.loginPath,
      enablePasswordValidation: !props.disablePasswordValidation,
    },
    callbacks: {
      submit,
      inputFunction,
    },
    refs: {
      formRef,
    },
  };
}
