import { isPostalCode } from "../../utils/isPostalCode";
import React, { useEffect, useMemo, useRef } from "react";
import { createPostalCodeMask } from "../../utils/inputMasking";
import FormInputField from "../FormInput";
import { useTranslation } from "react-i18next";

export const validatePostalCode =
  ({ selectedCountry, errorMessageInvalidFormat, t }) =>
  value => {
    if (!selectedCountry) {
      return false;
    }
    if (isPostalCode(value, selectedCountry)) {
      return true;
    }
    return errorMessageInvalidFormat || t("Please enter a valid Postal Code / Zip.");
  };

const PostalCode = ({
  register,
  errors,
  watch,
  setValue,
  name = "postalCode",
  id = "postalCode",
  countryName = "country",
  placeholder,
  label,
  errorMessageRequired,
  errorMessageInvalidFormat,
}) => {
  const { t } = useTranslation("components-form");
  const postalCodeError = errors?.[name];
  const [selectedCountry, currentPostalCode] = watch([countryName, name]);
  const postalCodeMask = useMemo(() => createPostalCodeMask(selectedCountry), [selectedCountry]);
  const postalCodeIsValid = postalCodeError === undefined;

  // Upon country change, reset the postalCode if it's invalid for the new country
  const prevCountry = useRef(selectedCountry);
  useEffect(() => {
    if (
      selectedCountry &&
      selectedCountry !== prevCountry.current &&
      !isPostalCode(currentPostalCode, selectedCountry)
    ) {
      setValue(name, undefined);
    }
    prevCountry.current = selectedCountry;
  }, [currentPostalCode, name, selectedCountry, setValue]);

  const { onChange: onPostalCodeChange, ...registeredPostalCode } = register(name, {
    required: errorMessageRequired || t("Please enter a valid Postal Code / Zip."),
    validate: {
      validPostalCode: validatePostalCode({ selectedCountry, errorMessageInvalidFormat, t }),
    },
  });

  return (
    <FormInputField
      id={id}
      type="text"
      label={label || t("Postal Code / Zip")}
      data-country={selectedCountry}
      required
      valid={postalCodeIsValid && selectedCountry && isPostalCode(currentPostalCode, selectedCountry)}
      {...registeredPostalCode}
      onChange={event => {
        if (postalCodeMask) {
          event.target.value = postalCodeMask.resolve(event.target.value);
        }
        // make sure this happens after we update the target.value with the masked value
        onPostalCodeChange(event);
      }}
      placeholder={placeholder}
      error={postalCodeError}
    />
  );
};
export default PostalCode;
