import { useRef as _, useCallback as U, useState as ie, useMemo as w, useEffect as K } from "react";
import { useFormControlContext as ce, extractEventHandlers as k } from "@mui/base";
import { useForkRef as pe } from "@mui/material";
import de from "@mui/material/utils/useId";
import { useControllableReducer as fe } from "@mui/base/utils/useControllableReducer";
import { isNumber as D } from "../../utils.js";
import { NUMBER_INPUT_KEY_COMPONENT as me } from "../../constants.js";
import { NumberInputActionTypes as o } from "./NumberInputActions.js";
import { numberInputReducer as ge } from "./NumberInputReducer.js";
const be = ["ArrowUp", "ArrowDown", "PageUp", "PageDown"], he = [...be, "Home", "End"];
function Ce(s) {
  return String(s && s.trim());
}
const Se = (s) => {
  const {
    min: d,
    max: f,
    step: N,
    withDecimal: T,
    shiftMultiplier: S = 10,
    value: m,
    inputRef: O,
    inputId: v,
    onChange: g,
    disabled: l = !1,
    onBlur: C,
    onFocus: q,
    onInputChange: Y,
    defaultValue: G,
    componentName: L = me,
    error: H = !1,
    required: x = !1,
    readOnly: j = !1
  } = s, a = ce(), { current: I } = _(m !== null), W = U((t) => {
    process.env.NODE_ENV !== "production" && t && t.nodeName !== "INPUT" && !t.focus && console.error(
      [
        "MUI: You have provided a `slots.input` to the input component",
        "that does not correctly handle the `ref` prop.",
        "Make sure the `ref` prop is called with a HTMLInputElement."
      ].join(`
`)
    );
  }, []), i = _(null), X = pe(i, O, W), R = de(v), [c, y] = ie(!1), z = U(
    (t, e, n, p) => {
      if (e === "value" && typeof n != "string")
        switch (p) {
          // only a blur event will dispatch `numberInput:clamp`
          case "numberInput:inputChange":
            g?.(t, n);
            break;
          // only a blur event will dispatch `numberInput:clamp`
          case "numberInput:clamp":
            g?.(t, n);
            break;
          case "numberInput:increment":
          case "numberInput:decrement":
          case "numberInput:incrementToMax":
          case "numberInput:decrementToMin":
            g?.(t, n);
            break;
        }
    },
    [g]
  ), B = w(() => ({
    min: d,
    max: f,
    step: N,
    withDecimal: T,
    shiftMultiplier: S,
    getInputValueAsString: Ce
  }), [d, f, N, T, S]), b = m ?? G ?? null, J = {
    value: b,
    inputValue: b ? String(b) : "",
    noControlledValue: b
  }, Q = w(
    () => ({
      value: m
    }),
    [m]
  ), [Z, r] = fe({
    reducer: ge,
    controlledProps: Q,
    initialState: J,
    onStateChange: z,
    actionContext: w(() => B, [B]),
    componentName: L
  }), { value: u, inputValue: h, noControlledValue: $ } = Z, ee = c && h !== "" ? $ !== Number(h) : !1;
  K(() => {
    !a && l && c && (y(!1), C?.());
  }, [a, l, c, C]), K(() => {
    I && D(u) && r({
      type: o.resetInputValue
    });
  }, [u, r, I]);
  const te = (t) => (e) => {
    t.onFocus?.(e), !(e.defaultMuiPrevented || e.defaultPrevented) && (a && a.onFocus && a?.onFocus?.(), y(!0));
  }, ne = (t) => (e) => {
    if (!I && e.target === null)
      throw (
        /* minify-error */
        new Error(
          "MUI: Expected valid input target. Did you use a custom `slots.input` and forget to forward refs? See https://mui.com/r/input-component-ref-interface for more info."
        )
      );
    a?.onChange?.(e), t.onInputChange?.(e), !(e.defaultMuiPrevented || e.defaultPrevented) && r({
      type: o.inputChange,
      event: e,
      inputValue: e.currentTarget.value
    });
  }, re = (t) => (e) => {
    a?.onBlur(), t.onBlur?.(e), !(e.defaultMuiPrevented || e.defaultPrevented) && (r({
      type: o.clamp,
      event: e,
      inputValue: e.currentTarget.value
    }), y(!1));
  }, oe = (t) => (e) => {
    t.onClick?.(e), !(e.defaultMuiPrevented || e.defaultPrevented) && i.current && e.currentTarget === e.target && i.current.focus();
  }, F = (t) => (e) => {
    const n = !!e.shiftKey, p = {
      up: o.increment,
      down: o.decrement
    }[t];
    r({
      type: p,
      event: e,
      applyMultiplier: n
    });
  }, ae = (t) => (e) => {
    if (t.onKeyDown?.(e), !(e.defaultMuiPrevented || e.defaultPrevented))
      switch (he.includes(e.key) && e.preventDefault(), e.key) {
        case "ArrowUp":
          r({
            type: o.increment,
            event: e,
            applyMultiplier: !!e.shiftKey
          });
          break;
        case "ArrowDown":
          r({
            type: o.decrement,
            event: e,
            applyMultiplier: !!e.shiftKey
          });
          break;
        case "PageUp":
          r({
            type: o.increment,
            event: e,
            applyMultiplier: !0
          });
          break;
        case "PageDown":
          r({
            type: o.decrement,
            event: e,
            applyMultiplier: !0
          });
          break;
        case "Home":
          r({
            type: o.decrementToMin,
            event: e
          });
          break;
        case "Enter":
          r({
            type: o.clamp,
            event: e,
            inputValue: e.currentTarget.value
          });
          break;
        case "End":
          r({
            type: o.incrementToMax,
            event: e
          });
          break;
      }
  }, ue = (t = {}) => {
    const n = {
      ...k(s, [
        // these are handled by the input slot
        "onBlur",
        "onInputChange",
        "onFocus",
        "onChange"
      ]),
      ...k(t)
    };
    return {
      ...t,
      ...n,
      onClick: oe(n)
    };
  }, le = (t = {}) => {
    const n = {
      ...{
        onBlur: C,
        onFocus: q,
        // onChange from normal props is the custom onChange so we ignore it here
        onChange: Y
      },
      ...k(t, [
        // onClick is handled by the root slot
        "onClick"
        // do not ignore 'onInputChange', we want slotProps.input.onInputChange to enter the DOM and throw
      ])
    }, p = {
      ...n,
      onFocus: te(n),
      // slotProps.onChange is renamed to onInputChange and passed to createHandleInputChange
      onChange: ne({
        ...n,
        onInputChange: n.onChange
      }),
      onBlur: re(n),
      onKeyDown: ae(n)
    }, M = (c ? h : u) ?? "";
    return delete t.onInputChange, {
      type: "text",
      id: R,
      "aria-invalid": H || void 0,
      defaultValue: void 0,
      value: M,
      "aria-valuenow": M,
      "aria-valuetext": String(M),
      "aria-valuemin": d,
      "aria-valuemax": f,
      autoComplete: "off",
      autoCorrect: "off",
      spellCheck: "false",
      required: !!x,
      readOnly: j,
      "aria-disabled": l,
      disabled: l,
      ...t,
      ref: X,
      ...p
    };
  }, V = (t) => {
    t.preventDefault(), i.current && i.current.focus();
  }, A = {
    "aria-controls": R,
    tabIndex: -1
  }, E = l || (D(u) ? u >= (f ?? Number.MAX_SAFE_INTEGER) : !1), se = (t = {}) => ({
    ...t,
    ...A,
    disabled: E,
    tabIndex: 0,
    "aria-disabled": E,
    onMouseDown: V,
    onClick: F("up")
  }), P = l || (D(u) ? u <= (d ?? Number.MIN_SAFE_INTEGER) : !1);
  return {
    disabled: l,
    error: H,
    focused: c,
    formControlContext: a,
    getInputProps: le,
    getIncrementButtonProps: se,
    getDecrementButtonProps: (t = {}) => ({
      ...t,
      ...A,
      disabled: P,
      tabIndex: 0,
      "aria-disabled": P,
      onMouseDown: V,
      onClick: F("down")
    }),
    getRootProps: ue,
    required: x,
    value: u,
    inputValue: h,
    isIncrementDisabled: E,
    isDecrementDisabled: P,
    focusError: ee
  };
};
export {
  Ce as getInputValueAsString,
  Se as useNumberInput
};
