import {
  SingleCodeInput
} from "./chunk-UZO5Y7WP.js";
import {
  textInputBorderColor
} from "./chunk-FTMB6R72.js";
import {
  __spreadProps,
  __spreadValues
} from "./chunk-W7FAWX6T.js";

// src/components/CodeInput/CodeInput.tsx
import styled from "@emotion/styled";
import { isNumber } from "lodash-es";
import { nanoid } from "nanoid";
import { createRef, useCallback, useRef, useState } from "react";
import { isChrome, isMobile, isMobileSafari } from "react-device-detect";
import { jsx, jsxs } from "@emotion/react/jsx-runtime";
function codeFromInputState(inputState) {
  return Object.values(inputState).map((input) => input.value).join("");
}
function getRef(key, refsObj) {
  if (key && refsObj && typeof refsObj === "object" && refsObj.current) {
    const ref = refsObj.current[key];
    if (ref && typeof ref === "object" && ref.current && ref.current instanceof HTMLInputElement) {
      return ref.current;
    }
  }
  return null;
}
function CodeInput({
  codeLength = 8,
  onChange,
  onSubmit,
  inputCSS,
  autoFocus = true,
  onBlur
}) {
  const componentId = useRef(nanoid(5));
  const inputRefs = useRef({});
  const autofillValuesRef = useRef("");
  const getInputId = useCallback((index) => {
    const idPrefix = `two-factor-input-${componentId.current}-`;
    return `${idPrefix}-${index}`;
  }, []);
  function getInputIndex(id) {
    return Number.parseInt(id.charAt(id.length - 1), 10);
  }
  const firstFieldRefCb = useCallback(
    (ref) => {
      if (ref) {
        inputRefs.current[ref.id] = createRef();
        inputRefs.current[ref.id].current = ref;
        if (ref.id === getInputId(0) && autoFocus) {
          ref.focus();
        }
      }
    },
    [getInputId, autoFocus]
  );
  const [inputState, setInputState] = useState(
    Array(codeLength).fill(0).reduce((acc, _, i) => {
      return __spreadProps(__spreadValues({}, acc), {
        [getInputId(i)]: {
          value: ""
        }
      });
    }, {})
  );
  const onKeyDown = useCallback(
    (event, inputId) => {
      const handleKeys = /* @__PURE__ */ new Set([
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "Enter",
        "Escape",
        "Backspace",
        "Delete",
        "ArrowLeft",
        "ArrowRight"
      ]);
      if (["e", "E", "+", "-", "."].includes(event.key)) {
        event.preventDefault();
        return;
      }
      if (!handleKeys.has(event.key)) {
        return;
      }
      let replaceEntireState = false;
      const currentInputIndex = getInputIndex(inputId);
      const isFirstInput = currentInputIndex === 0;
      const isLastInput = currentInputIndex === codeLength - 1;
      const nextInputIndex = isLastInput ? void 0 : currentInputIndex + 1;
      const prevInputIndex = isFirstInput ? void 0 : currentInputIndex - 1;
      const nextInputId = isNumber(nextInputIndex) ? getInputId(nextInputIndex) : void 0;
      const prevInputId = isNumber(prevInputIndex) ? getInputId(prevInputIndex) : void 0;
      const nextInput = nextInputId ? inputState[nextInputId] : void 0;
      const prevInput = prevInputId ? inputState[prevInputId] : void 0;
      const currentInputRef = getRef(inputId, inputRefs);
      const nextInputRef = getRef(nextInputId, inputRefs);
      const prevInputRef = getRef(prevInputId, inputRefs);
      const firstInputRef = getRef(getInputId(0), inputRefs);
      const lastInputRef = getRef(getInputId(codeLength - 1), inputRefs);
      if (event.key === "ArrowLeft") {
        if (firstInputRef && (event.metaKey || event.ctrlKey || event.altKey)) {
          firstInputRef.focus();
          return;
        }
        if (prevInput && prevInputRef) {
          prevInputRef.focus();
          prevInputRef.select();
        }
        return;
      }
      if (event.key === "ArrowRight") {
        if (lastInputRef && (event.metaKey || event.ctrlKey || event.altKey)) {
          lastInputRef.focus();
          return;
        }
        if (nextInput && nextInputRef) {
          nextInputRef.focus();
          nextInputRef.select();
        }
        return;
      }
      if (event.key === "Enter" && onSubmit) {
        const code2 = codeFromInputState(inputState);
        onSubmit(code2);
        return;
      }
      if (event.key === "Escape" && currentInputRef) {
        currentInputRef.blur();
        return;
      }
      if (event.key === "Backspace" && (event.metaKey || event.ctrlKey || event.altKey)) {
        replaceEntireState = __spreadValues({}, inputState);
        Object.keys(replaceEntireState).forEach((inputId2) => {
          const newState2 = replaceEntireState;
          newState2[inputId2] = __spreadProps(__spreadValues({}, newState2[inputId2]), {
            value: ""
          });
        });
      }
      let value = event.key;
      if (event.key === "Backspace" && !event.metaKey && !event.ctrlKey && !event.altKey) {
        value = "";
        if (!isFirstInput && prevInput && prevInputRef) {
          prevInputRef.focus();
        }
      } else if (event.key === "Delete") {
        value = "";
        if (!isLastInput && nextInput && nextInputRef) {
          nextInputRef.focus();
        }
      } else if (replaceEntireState) {
        const lastInputWithValue = Object.entries(replaceEntireState).reverse().find(([, { value: value2 }]) => value2 !== "");
        if (lastInputWithValue) {
          const inputId2 = lastInputWithValue[0];
          const inputRef = getRef(inputId2, inputRefs);
          inputRef == null ? void 0 : inputRef.focus();
          inputRef == null ? void 0 : inputRef.select();
        } else if (firstInputRef) {
          firstInputRef.focus();
        }
      } else if (isLastInput) {
      } else if (nextInput && nextInputRef) {
        nextInputRef.focus();
        nextInputRef.select();
      }
      const newState = replaceEntireState ? replaceEntireState : __spreadProps(__spreadValues({}, inputState), {
        [inputId]: { value }
      });
      const code = codeFromInputState(newState);
      if (onChange) {
        onChange(code);
      }
      setInputState(newState);
    },
    [onChange, setInputState, onSubmit, getInputId, inputState, codeLength]
  );
  const onPasteCb = useCallback(
    (event) => {
      event.preventDefault();
      const rawText = event.clipboardData.getData("text");
      const text = rawText == null ? void 0 : rawText.replace(/[\s.]/g, "");
      if (!text || Number.isNaN(Number.parseInt(text))) {
        return;
      }
      const inputValues = text.split("");
      const newState = __spreadValues({}, inputState);
      inputValues.forEach((value, i) => {
        const inputId = getInputId(i);
        newState[inputId] = __spreadProps(__spreadValues({}, newState[inputId]), {
          value
        });
      });
      const firstInputRef = getRef(getInputId(0), inputRefs);
      const lastInputWithValue = Object.entries(newState).reverse().find(([, { value }]) => value !== "");
      if (lastInputWithValue) {
        const inputId = lastInputWithValue[0];
        const inputRef = getRef(inputId, inputRefs);
        inputRef == null ? void 0 : inputRef.focus();
        inputRef == null ? void 0 : inputRef.select();
      } else if (firstInputRef) {
        firstInputRef.focus();
      }
      const code = codeFromInputState(newState);
      if (onChange) {
        onChange(code);
      }
      setInputState(newState);
    },
    [getInputId, inputState, onChange, setInputState]
  );
  const onBlurCb = useCallback(() => {
    setTimeout(() => {
      let hasCodeFocused = false;
      if (inputRefs.current) {
        Object.values(inputRefs.current).forEach((ref) => {
          if (ref && ref.current && ref.current === document.activeElement) {
            hasCodeFocused = true;
          }
        });
        if (!hasCodeFocused && onBlur) {
          onBlur();
        }
      }
    }, 0);
  }, [onBlur]);
  const inputsPerGroup = Math.ceil(codeLength / 2);
  const inputs = [];
  for (let i = 0; i < codeLength; i += 1) {
    const inputId = getInputId(i);
    inputs.push(
      /* @__PURE__ */ jsx(
        SingleCodeInput,
        {
          value: inputState[inputId].value,
          id: inputId,
          inputRef: firstFieldRefCb,
          onPaste: onPasteCb,
          onKeyDown: (event) => onKeyDown(event, inputId),
          onChange: (event) => {
            if (isMobileSafari && event.nativeEvent instanceof CustomEvent) {
              autofillValuesRef.current += event.target.value;
              if (autofillValuesRef.current.length === codeLength) {
                const newState = Array(codeLength).fill(0).reduce((acc, _, i2) => {
                  return __spreadProps(__spreadValues({}, acc), {
                    [getInputId(i2)]: {
                      value: autofillValuesRef.current[i2]
                    }
                  });
                }, {});
                setInputState(newState);
                if (onSubmit) {
                  onSubmit(autofillValuesRef.current);
                }
                autofillValuesRef.current = "";
              }
            } else if (isMobile && isChrome && event.target.value.length === codeLength) {
              const newState = Array(codeLength).fill(0).reduce((acc, _, i2) => {
                return __spreadProps(__spreadValues({}, acc), {
                  [getInputId(i2)]: {
                    value: event.target.value[i2]
                  }
                });
              }, {});
              setInputState(newState);
              if (onSubmit) {
                onSubmit(event.target.value);
              }
            }
          },
          type: "number",
          ariaLabel: `Code input ${i + 1} of ${codeLength}`,
          cssProp: inputCSS,
          onBlur: onBlurCb,
          width: `${(100 / inputsPerGroup).toFixed(2)}%`,
          max: 9
        },
        inputId
      )
    );
  }
  return /* @__PURE__ */ jsxs(StyledCodeInput, { children: [
    /* @__PURE__ */ jsx(CodeInputGroup, { children: inputs.slice(0, inputsPerGroup) }),
    /* @__PURE__ */ jsx(CodeInputGroupSeparator, {}),
    /* @__PURE__ */ jsx(CodeInputGroup, { children: inputs.slice(inputsPerGroup, inputs.length) })
  ] });
}
var StyledCodeInput = styled.div`
  display: inline-flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
`;
var separatorWidth = 12;
var separatorMargin = 8;
var CodeInputGroup = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  width: calc(50% - ${(separatorWidth + separatorMargin * 2) / 2}px);
`;
var CodeInputGroupSeparator = styled.div`
  width: ${separatorWidth}px;
  height: 4px;
  background-color: ${textInputBorderColor};
  border-radius: 2px;
  margin: 0 ${separatorMargin}px;
`;

export {
  CodeInput,
  StyledCodeInput
};
