import { useMutation, useParent, useParentQueryValue, useParentValue, useQuery, useUserIdentity, } from "@saasquatch/component-boilerplate";
import { useEffect, useMemo, useRef, useState, } from "@saasquatch/universal-hooks";
import jsonpointer from "jsonpointer";
import { CURRENCIES_NAMESPACE, SORTED_COUNTRIES_NAMESPACE, TAX_CONTEXT_NAMESPACE, TAX_FORM_CONTEXT_NAMESPACE, USER_FORM_CONTEXT_NAMESPACE, USER_QUERY_NAMESPACE, } from "../data";
import { ADDRESS_REGIONS } from "../subregions";
import { objectIsFull, validTaxDocument } from "../utils";
import { TAX_FORM_UPDATED_EVENT_KEY } from "../eventKeys";
import { CONNECT_PARTNER, } from "../sqm-indirect-tax-form/useIndirectTaxForm";
import { gql } from "graphql-request";
const GET_INDIRECT_TAX_COUNTRY_CODE = gql `
  query getIndirectTaxCountryCode {
    tenantSettings {
      impactBrandCountryCode
      impactBrandIndirectTaxCountryCode
    }
  }
`;
export function useUserInfoForm(props) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
  const currencyRef = useRef(undefined);
  const phoneCountryRef = useRef(undefined);
  const formRef = useRef(null);
  const context = useParentValue(TAX_FORM_CONTEXT_NAMESPACE);
  const countries = useParentValue(SORTED_COUNTRIES_NAMESPACE);
  const [step, setStep] = useParent(TAX_CONTEXT_NAMESPACE);
  const [userFormContext, setUserFormContext] = useParent(USER_FORM_CONTEXT_NAMESPACE);
  const user = useUserIdentity();
  const [connectImpactPartner, { loading: connectLoading, errors: connectErrors },] = useMutation(CONNECT_PARTNER);
  const { data: tenantData } = useQuery(GET_INDIRECT_TAX_COUNTRY_CODE, {});
  const { data, loading, refetch, errors: userError, } = useParentQueryValue(USER_QUERY_NAMESPACE);
  const _currencies = useParentValue(CURRENCIES_NAMESPACE);
  const currencies = useMemo(() => [...(_currencies || [])].sort((a, b) => a.displayName.localeCompare(b.displayName)), [_currencies]);
  const [countrySearch, setCountrySearch] = useState("");
  const [phoneCountrySearch, setPhoneCountrySearch] = useState("");
  const [filteredCountries, setFilteredCountries] = useState(countries || []);
  const [filteredPhoneCountries, setFilteredPhoneCountries] = useState(countries || []);
  const [currencySearch, setCurrencySearch] = useState("");
  const [filteredCurrencies, setFilteredCurrencies] = useState(currencies || []);
  const [formErrors, setErrors] = useState({});
  useEffect(() => {
    // reset redirect hash
    window.location.hash = "";
  }, []);
  useEffect(() => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
    const user = data === null || data === void 0 ? void 0 : data.user;
    if (!user || step !== "/1")
      return;
    // If form already filled out, skip initialising it
    if (objectIsFull(userFormContext))
      return;
    // Prefer MI email if it was verified before this
    const email = ((_a = user.managedIdentity) === null || _a === void 0 ? void 0 : _a.emailVerified) ? user.managedIdentity.email
      : user.email;
    if (((_b = user.impactConnection) === null || _b === void 0 ? void 0 : _b.publisher) && ((_c = user.impactConnection) === null || _c === void 0 ? void 0 : _c.user)) {
      // Initialise with partner information
      setUserFormContext({
        email,
        firstName: user.impactConnection.user.firstName,
        lastName: user.impactConnection.user.lastName,
        countryCode: user.impactConnection.publisher.countryCode,
        currency: user.impactConnection.publisher.currency,
        phoneNumberCountryCode: user.impactConnection.publisher.phoneNumberCountryCode,
        phoneNumber: user.impactConnection.publisher.phoneNumber,
        address: user.impactConnection.publisher.billingAddress,
        city: user.impactConnection.publisher.billingCity,
        state: user.impactConnection.publisher.billingState,
        postalCode: user.impactConnection.publisher.billingPostalCode,
      });
    }
    else if (!(userFormContext === null || userFormContext === void 0 ? void 0 : userFormContext.email)) {
      // Initialise with user information
      setUserFormContext({
        email,
        firstName: ((_e = (_d = user.impactConnection) === null || _d === void 0 ? void 0 : _d.user) === null || _e === void 0 ? void 0 : _e.firstName) || user.firstName,
        lastName: ((_g = (_f = user.impactConnection) === null || _f === void 0 ? void 0 : _f.user) === null || _g === void 0 ? void 0 : _g.lastName) || user.lastName,
        countryCode: user.countryCode || "US",
        currency: (_h = user.customFields) === null || _h === void 0 ? void 0 : _h.currency,
        phoneNumberCountryCode: ((_j = user.customFields) === null || _j === void 0 ? void 0 : _j.phoneNumberCountryCode) || "US",
        phoneNumber: (_k = user.customFields) === null || _k === void 0 ? void 0 : _k.phoneNumber,
        address: (_l = user.customFields) === null || _l === void 0 ? void 0 : _l.address,
        city: (_m = user.customFields) === null || _m === void 0 ? void 0 : _m.city,
        state: (_o = user.customFields) === null || _o === void 0 ? void 0 : _o.state,
        postalCode: (_p = user.customFields) === null || _p === void 0 ? void 0 : _p.postalCode,
      });
    }
  }, [data, step, userFormContext]);
  const onFormChange = (field, e) => {
    var _a, _b;
    const value = (_b = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.item) === null || _b === void 0 ? void 0 : _b.__value;
    if (!value)
      console.error("Could not detect select change");
    setUserFormContext({
      ...userFormContext,
      [field]: value,
    });
    if (field === "countryCode") {
      phoneCountryRef.current.value = value;
      currencyRef.current.value = "";
    }
  };
  useEffect(() => {
    if (!(countries === null || countries === void 0 ? void 0 : countries.length))
      return;
    if (countrySearch.trim() === "") {
      setFilteredCountries(countries || []);
    }
    else {
      setFilteredCountries(countries.filter((c) => c.displayName.toLowerCase().includes(countrySearch.toLowerCase())) || []);
    }
  }, [countrySearch, countries]);
  useEffect(() => {
    if (!(countries === null || countries === void 0 ? void 0 : countries.length))
      return;
    if (phoneCountrySearch.trim() === "") {
      setFilteredPhoneCountries(countries || []);
    }
    else {
      setFilteredPhoneCountries(countries.filter((c) => c.displayName
        .toLowerCase()
        .includes(phoneCountrySearch.toLowerCase())) || []);
    }
  }, [phoneCountrySearch, countries]);
  useEffect(() => {
    if (!(currencies === null || currencies === void 0 ? void 0 : currencies.length))
      return;
    if (currencySearch.trim() === "") {
      setFilteredCurrencies(currencies || []);
    }
    else {
      setFilteredCurrencies(currencies.filter((c) => c.currencyCode.toLowerCase().includes(currencySearch.toLowerCase())) || []);
    }
  }, [currencySearch, currencies]);
  async function connectPartner(formData) {
    var _a, _b, _c, _d, _e;
    const vars = {
      user: {
        id: user.id,
        accountId: user.accountId,
      },
      firstName: formData.firstName,
      lastName: formData.lastName,
      countryCode: formData.countryCode,
      currency: formData.currency,
      address: formData.address,
      city: formData.city,
      state: formData.state,
      postalCode: formData.postalCode,
      phoneNumber: formData.phoneNumber,
      phoneNumberCountryCode: formData.phoneNumberCountryCode,
    };
    const result = await connectImpactPartner({
      vars,
    });
    if (!result || ((_a = result) === null || _a === void 0 ? void 0 : _a.message))
      throw new Error();
    if (!((_b = result.createImpactConnection) === null || _b === void 0 ? void 0 : _b.success)) {
      // Output backend errors to console for now
      console.error("Failed to create Impact connection: ", result.createImpactConnection
        .validationErrors);
      throw new Error();
    }
    await refetch();
    const resultPublisher = (_e = (_d = (_c = result
      .createImpactConnection) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.impactConnection) === null || _e === void 0 ? void 0 : _e.publisher;
    const hasValidCurrentDocument = validTaxDocument(resultPublisher === null || resultPublisher === void 0 ? void 0 : resultPublisher.requiredTaxDocumentType) && (resultPublisher === null || resultPublisher === void 0 ? void 0 : resultPublisher.currentTaxDocument);
    // Fire form change event
    window.dispatchEvent(new Event(TAX_FORM_UPDATED_EVENT_KEY));
    return {
      resultPublisher,
      hasValidCurrentDocument,
    };
  }
  async function onSubmit(event) {
    let formControls = event.target.getFormControls();
    let formData = {};
    let errors = {};
    formControls === null || formControls === void 0 ? void 0 : formControls.forEach((control) => {
      if (!control.name)
        return;
      const key = control.name;
      const value = control.value;
      // custom validation
      if (typeof control.validationError === "function") {
        const validate = control.validationError;
        const validationError = validate({ control, key, value });
        if (validationError)
          jsonpointer.set(errors, key, validationError);
      }
      // required validation
      if (control.required) {
        if (!value || (typeof value === "string" && value.trim() === ""))
          jsonpointer.set(errors, key, props.fieldRequiredError);
      }
      jsonpointer.set(formData, key, value);
    });
    if (Object.keys(errors).length) {
      setErrors(errors);
      // early return for validation errors
      return;
    }
    const { allowBankingCollection, ...userData } = formData;
    setUserFormContext({
      ...userFormContext,
      firstName: userData.firstName,
      lastName: userData.lastName,
      phoneNumberCountryCode: userData.phoneNumberCountryCode,
      phoneNumber: userData.phoneNumber,
      countryCode: userData.countryCode,
      address: userData.address,
      city: userData.city,
      state: userData.state,
      postalCode: userData.postalCode,
      currency: userData.currency,
    });
    const skipNextStep = getSkipNextStep(userData);
    if (skipNextStep) {
      try {
        const { resultPublisher, hasValidCurrentDocument } = await connectPartner(formData);
        if ((resultPublisher === null || resultPublisher === void 0 ? void 0 : resultPublisher.requiredTaxDocumentType) &&
          !hasValidCurrentDocument) {
          // Go to docusign form
          setStep("/3");
        }
        else {
          if (resultPublisher === null || resultPublisher === void 0 ? void 0 : resultPublisher.brandedSignup) {
            // Go to banking information form
            setStep("/4");
          }
          else {
            // Go right to the dashboard
            setStep("/dashboard");
          }
        }
        return;
      }
      catch (e) {
        setErrors({ general: true });
        return;
      }
    }
    const nextStep = context.overrideNextStep || skipNextStep ? "/3" : "/2";
    setStep(nextStep);
  }
  const indirectTaxCountry = (_a = tenantData === null || tenantData === void 0 ? void 0 : tenantData.tenantSettings) === null || _a === void 0 ? void 0 : _a.impactBrandIndirectTaxCountryCode;
  const hasIndirectTax = !!indirectTaxCountry;
  function getSkipNextStep(userData) {
    if (!hasIndirectTax)
      return true;
    if (userData.countryCode === "US")
      return true;
    if (hasIndirectTax && userData.countryCode !== indirectTaxCountry)
      return true;
    return false;
  }
  const hasStates = ["ES", "AU", "US", "CA"].includes(userFormContext.countryCode);
  const regionObj = hasStates
    ? ADDRESS_REGIONS[userFormContext === null || userFormContext === void 0 ? void 0 : userFormContext.countryCode]
    : {};
  return {
    setStep: setStep,
    onSubmit,
    text: props.getTextProps(),
    callbacks: {
      setCurrencySearch,
      setCountrySearch,
      setPhoneCountrySearch,
      onFormChange,
    },
    refs: {
      formRef,
      currencyRef,
      phoneCountryRef,
    },
    data: {
      currencies: filteredCurrencies,
      countries: filteredCountries,
      phoneCountries: filteredPhoneCountries,
      allCurrencies: currencies,
      allCountries: countries,
      regionLabelEnum: regionObj === null || regionObj === void 0 ? void 0 : regionObj.labelEnum,
      regions: (regionObj === null || regionObj === void 0 ? void 0 : regionObj.regions) || [],
      partnerData: (_c = (_b = data === null || data === void 0 ? void 0 : data.user) === null || _b === void 0 ? void 0 : _b.impactConnection) === null || _c === void 0 ? void 0 : _c.publisher,
      userData: (_e = (_d = data === null || data === void 0 ? void 0 : data.user) === null || _d === void 0 ? void 0 : _d.impactConnection) === null || _e === void 0 ? void 0 : _e.user,
    },
    states: {
      step: step === null || step === void 0 ? void 0 : step.replace("/", ""),
      hideState: !hasStates,
      hideSteps: !!context.hideSteps,
      disabled: loading || connectLoading,
      loadingError: !!(userError === null || userError === void 0 ? void 0 : userError.message),
      loading: loading || connectLoading,
      isPartner: !!((_g = (_f = data === null || data === void 0 ? void 0 : data.user) === null || _f === void 0 ? void 0 : _f.impactConnection) === null || _g === void 0 ? void 0 : _g.publisher),
      isUser: !!((_j = (_h = data === null || data === void 0 ? void 0 : data.user) === null || _h === void 0 ? void 0 : _h.impactConnection) === null || _j === void 0 ? void 0 : _j.user),
      formState: {
        ...userFormContext,
        errors: formErrors,
      },
    },
  };
}
