import { useLocale, useMutation, useParent, useParentQueryValue, useParentValue, useUserIdentity, } from "@saasquatch/component-boilerplate";
import { useEffect, useMemo, useRef, useState, } from "@saasquatch/universal-hooks";
import { gql } from "graphql-request";
import JSONPointer from "jsonpointer";
import { COUNTRIES_QUERY_NAMESPACE, TAX_CONTEXT_NAMESPACE, TAX_FORM_CONTEXT_NAMESPACE, USER_FORM_CONTEXT_NAMESPACE, USER_QUERY_NAMESPACE, } from "../data";
import { TAX_FORM_UPDATED_EVENT_KEY } from "../eventKeys";
import { INDIRECT_TAX_PROVINCES, INDIRECT_TAX_SPAIN_REGIONS, } from "../subregions";
import { getCountryObj, validTaxDocument } from "../utils";
export const CONNECT_PARTNER = gql `
  mutation createImpactConnection($vars: ImpactConnectionInput!) {
    createImpactConnection(impactConnectionInput: $vars) {
      success
      validationErrors {
        field
        message
      }
      user {
        id
        accountId
        impactConnection {
          connected
          publisher {
            brandedSignup
            requiredTaxDocumentType
            currentTaxDocument {
              type
              status
            }
          }
        }
      }
    }
  }
`;
function getOption(countries, countryCode) {
  if (!countries)
    return;
  if (countries.find((c) => c.countryCode === countryCode)) {
    return "otherRegion";
  }
  else {
    return "notRegistered";
  }
}
export function useIndirectTaxForm(props) {
  var _a, _b, _c, _d, _e;
  const user = useUserIdentity();
  const locale = useLocale();
  const formRef = useRef(null);
  const context = useParentValue(TAX_FORM_CONTEXT_NAMESPACE);
  const [step, setStep] = useParent(TAX_CONTEXT_NAMESPACE);
  const [connectImpactPartner, { loading: connectLoading, errors: connectErrors },] = useMutation(CONNECT_PARTNER);
  const userForm = useParentValue(USER_FORM_CONTEXT_NAMESPACE);
  const { data: userData, refetch, errors: userError, } = useParentQueryValue(USER_QUERY_NAMESPACE);
  const { data: _countriesRes, loading: countriesLoading } = useParentQueryValue(COUNTRIES_QUERY_NAMESPACE);
  const intlLocale = (locale === null || locale === void 0 ? void 0 : locale.replace("_", "-")) || "en";
  const _countries = useMemo(() => { var _a, _b; return (_b = (_a = _countriesRes === null || _countriesRes === void 0 ? void 0 : _countriesRes.impactPayoutCountries) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.map((country) => getCountryObj({ countryCode: country.countryCode, locale: intlLocale })); }, [(_a = _countriesRes === null || _countriesRes === void 0 ? void 0 : _countriesRes.impactPayoutCountries) === null || _a === void 0 ? void 0 : _a.data]);
  const [loading, setLoading] = useState(false);
  const [formState, setFormState] = useState({});
  const [errors, setErrors] = useState({});
  const [countrySearch, setCountrySearch] = useState("");
  const [filteredCountries, setFilteredCountries] = useState(_countries || []);
  const [option, setOption] = useState("notRegistered");
  const publisher = (_c = (_b = userData === null || userData === void 0 ? void 0 : userData.user) === null || _b === void 0 ? void 0 : _b.impactConnection) === null || _c === void 0 ? void 0 : _c.publisher;
  useEffect(() => {
    // reset redirect hash
    window.location.hash = "";
  }, []);
  useEffect(() => {
    var _a;
    if (!((_a = publisher === null || publisher === void 0 ? void 0 : publisher.taxInformation) === null || _a === void 0 ? void 0 : _a.indirectTaxCountryCode))
      return;
    const _option = getOption(_countries, publisher.taxInformation.indirectTaxCountryCode);
    setOption(_option);
  }, [publisher, _countries]);
  useEffect(() => {
    if (countrySearch.trim() === "") {
      setFilteredCountries(_countries || []);
    }
    else {
      setFilteredCountries((_countries === null || _countries === void 0 ? void 0 : _countries.filter((c) => c.displayName.toLowerCase().includes(countrySearch.toLowerCase()))) || []);
    }
  }, [countrySearch, _countries]);
  useEffect(() => {
    var _a, _b;
    const user = userData === null || userData === void 0 ? void 0 : userData.user;
    if (!user)
      return;
    if ((_b = (_a = user.impactConnection) === null || _a === void 0 ? void 0 : _a.publisher) === null || _b === void 0 ? void 0 : _b.taxInformation) {
      setFormState({
        province: user.impactConnection.publisher.taxInformation.indirectTaxRegion,
        subRegion: user.impactConnection.publisher.taxInformation.indirectTaxRegion,
        hasQst: !!user.impactConnection.publisher.taxInformation.additionalTaxId,
        qstNumber: user.impactConnection.publisher.taxInformation.additionalTaxId,
        hasSubRegionTaxNumber: !!user.impactConnection.publisher.taxInformation.withholdingTaxId,
        subRegionTaxNumber: user.impactConnection.publisher.taxInformation.withholdingTaxId,
        selectedRegion: user.impactConnection.publisher.taxInformation.indirectTaxCountryCode,
        indirectTaxNumber: user.impactConnection.publisher.taxInformation.indirectTaxId,
      });
    }
    else {
      setFormState({
        selectedRegion: (user === null || user === void 0 ? void 0 : user.countryCode) || (userForm === null || userForm === void 0 ? void 0 : userForm.countryCode),
      });
    }
  }, [userData, userForm]);
  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");
    setFormState((p) => ({ ...p, [field]: value }));
  };
  async function connectPartner(formData) {
    var _a, _b, _c, _d, _e;
    const vars = {
      user: {
        id: user.id,
        accountId: user.accountId,
      },
      firstName: userForm.firstName,
      lastName: userForm.lastName,
      countryCode: userForm.countryCode,
      currency: userForm.currency,
      address: userForm.address,
      city: userForm.city,
      state: userForm.state,
      postalCode: userForm.postalCode,
      phoneNumber: userForm.phoneNumber,
      phoneNumberCountryCode: userForm.phoneNumberCountryCode,
      indirectTaxCountryCode: formData.selectedRegion,
      indirectTaxRegion: formData.province || formData.subRegion,
      indirectTaxId: formData.indirectTaxNumber,
      additionalTaxId: formData.qstNumber,
      withholdingTaxId: formData.subRegionTaxNumber,
    };
    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,
    };
  }
  const onSubmit = async (event) => {
    if (!option) {
      setErrors({ taxDetails: true });
      return;
    }
    let formData = { taxOption: option };
    let validationErrors = {};
    const controls = event.target.getFormControls();
    controls.forEach((control) => {
      if (!control.name || !control.id)
        return;
      if (option === "notRegistered")
        return; // Don't include fields for notRegistered option
      const key = control.name;
      const value = control.value;
      JSONPointer.set(formData, key, value);
      if (control.required && !value) {
        JSONPointer.set(validationErrors, key, true);
      }
    });
    setErrors(validationErrors);
    if (Object.keys(validationErrors).length) {
      return;
    }
    setLoading(true);
    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");
        }
      }
    }
    catch (e) {
      setErrors({ general: true });
    }
    finally {
      setLoading(false);
    }
  };
  const onBack = () => {
    setStep(context.overrideBackStep || "/1");
  };
  return {
    states: {
      step: step === null || step === void 0 ? void 0 : step.replace("/", ""),
      hideSteps: context.hideSteps,
      disabled: loading || countriesLoading || connectLoading,
      loading: loading || connectLoading || countriesLoading,
      isPartner: !!((_e = (_d = userData === null || userData === void 0 ? void 0 : userData.user) === null || _d === void 0 ? void 0 : _d.impactConnection) === null || _e === void 0 ? void 0 : _e.publisher),
      loadingError: !!(userError === null || userError === void 0 ? void 0 : userError.message),
      formState: {
        checked: option,
        errors,
      },
    },
    callbacks: {
      onBack,
      onSubmit,
      onFormChange,
      onChange: setOption,
      setCountrySearch,
      onQstToggle: () => setFormState((p) => ({ ...p, hasQst: !p.hasQst })),
      onSpainToggle: () => setFormState((p) => ({
        ...p,
        hasSubRegionTaxNumber: !p.hasSubRegionTaxNumber,
      })),
    },
    data: {
      esRegions: INDIRECT_TAX_SPAIN_REGIONS,
      countries: filteredCountries,
      allCountries: _countries,
      provinces: INDIRECT_TAX_PROVINCES,
    },
    text: props.getTextProps(),
    refs: {
      formRef,
    },
    slotProps: {
      formState: {
        ...formState,
        errors,
      },
    },
  };
}
