import { motion, type HTMLMotionProps } from "motion/react";
import clsx, { type ClassValue } from "clsx";
import { type ReactNode, useRef, useState, type ChangeEvent, useId } from "react";
import KeyboardIcon from "@components/icons/KeyboardIcon";

import classes from "./NumberInput.module.css";
import { usePlaySound } from "@/audio";
import tg from "@/tg";

type Props = Omit<HTMLMotionProps<"input">, "className" | "type" | "onChange"> & {
  className?: ClassValue;
  error?: boolean;
  prefix?: ReactNode;
  value?: number;
  onChange?: (value: number) => void;
};

const NUMERIC_REGEX = /[^0-9.]/g;

function filterNumericInput(input: string): string {
  const filtered = input.replace(NUMERIC_REGEX, "");
  const parts = filtered.split(".");
  return parts.length > 2 ? `${parts[0]}.${parts.slice(1).join("")}` : filtered;
}

export default function NumberInput({
  className,
  error,
  prefix,
  value,
  onChange,
  ...props
}: Props) {
  const play = usePlaySound();

  const stableId = useId();
  const inputRef = useRef<HTMLInputElement>(null);
  const id = props.id ?? stableId;

  const [strValue, setStrValue] = useState(() => value?.toString() ?? "");
  const prevValueRef = useRef(value);
  if (prevValueRef.current !== value) {
    prevValueRef.current = value;
    setStrValue(value?.toString() ?? "");
  }

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const normalized = filterNumericInput(e.target.value);
    setStrValue(normalized);
    const num = parseFloat(normalized);
    onChange?.(isNaN(num) ? 0 : num);
  };

  return (
    <div className={clsx(classes.container, error && classes.error, className)}>
      <label className={classes.inputWrapper} htmlFor={id}>
        {prefix && <span className={classes.prefix}>{prefix}</span>}
        <motion.input
          placeholder="0"
          {...props}
          id={id}
          ref={inputRef}
          type="text"
          inputMode="numeric"
          className={classes.input}
          value={strValue}
          onChange={handleChange}
        />
      </label>
      <motion.button
        whileTap={{ scale: 0.95 }}
        className={classes.iconButton}
        onClick={() => {
          play("click");
          tg.hapticFeedback.click();
          inputRef.current?.focus();
        }}
      >
        <KeyboardIcon className={classes.icon} />
      </motion.button>
    </div>
  );
}
