import * as React from "react";

import { Input } from "@/components/ui/input";

/**
 * Money input backed by an integer "cents" value but edited in pounds.
 *
 * Uses type=text (not type=number) so there are no spinner arrows and the field
 * accepts free keyboard entry — including partial values like "10." mid-typing.
 * The displayed text is the source of truth while focused; we only re-sync from
 * the model when it genuinely diverges (e.g. a different record loads), so the
 * cursor never fights the rounded value we emit on each keystroke.
 */
export function PoundsField({
  cents,
  onChange,
  id,
  placeholder,
  disabled,
  className,
}: {
  cents: number;
  onChange: (cents: number) => void;
  id?: string;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
}) {
  const toText = (c: number) => (c ? String(c / 100) : "");
  const [text, setText] = React.useState(() => toText(cents));

  React.useEffect(() => {
    if (Math.round((parseFloat(text) || 0) * 100) !== cents) setText(toText(cents));
    // Only resync when the upstream value changes — not on our own emissions.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [cents]);

  return (
    <Input
      id={id}
      type="text"
      inputMode="decimal"
      placeholder={placeholder}
      disabled={disabled}
      className={className}
      value={text}
      onChange={(e) => {
        const raw = e.target.value;
        // Digits with an optional decimal point and up to two decimal places.
        if (raw !== "" && !/^\d*\.?\d{0,2}$/.test(raw)) return;
        setText(raw);
        onChange(Math.round((parseFloat(raw) || 0) * 100));
      }}
    />
  );
}

/**
 * Plain non-negative integer input. Same free-typing behaviour as PoundsField —
 * no spinner arrows, accepts direct keyboard entry. Any min/max bounds are left
 * to server-side validation so typing is never interrupted mid-entry.
 */
export function IntegerField({
  value,
  onChange,
  id,
  placeholder,
  disabled,
  className,
}: {
  value: number;
  onChange: (value: number) => void;
  id?: string;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
}) {
  const toText = (n: number) => (Number.isFinite(n) ? String(n) : "");
  const [text, setText] = React.useState(() => toText(value));

  React.useEffect(() => {
    if ((parseInt(text || "", 10) || 0) !== value) setText(toText(value));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value]);

  return (
    <Input
      id={id}
      type="text"
      inputMode="numeric"
      placeholder={placeholder}
      disabled={disabled}
      className={className}
      value={text}
      onChange={(e) => {
        const raw = e.target.value;
        if (raw !== "" && !/^\d*$/.test(raw)) return;
        setText(raw);
        onChange(parseInt(raw || "0", 10) || 0);
      }}
    />
  );
}
