import React, { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group";

/**
 * Numeric input for interest rates with a "%" suffix.
 * Accepts 0–max with one decimal place. Strips the slider from the app's
 * InterestRateInput — use this wherever just the rate field is needed.
 *
 * Consumers should wrap in <Field> + <FieldLabel> / <FieldError> for label/error display.
 */

export type InterestRateInputProps = {
  /** Current rate value (e.g. 5.5 for 5.5%) */
  value: number;
  /** Called on blur with the parsed, validated value */
  onChange: (value: number) => void;
  /** HTML id forwarded to the inner <input> */
  id?: string;
  /** Minimum allowed value (default: 0) */
  min?: number;
  /** Maximum allowed value (default: 10) */
  max?: number;
  disabled?: boolean;
  /** When true, renders the InputGroup in its error visual state */
  error?: boolean;
  className?: string;
};

/** Allow one decimal place: 0–max (e.g. "5", "5.", "5.5", "10.0") */
function buildValidationRegex(max: number): RegExp {
  const intMax = Math.floor(max);
  // Matches: integer part 0–max, optional single decimal digit
  return new RegExp(`^(${intMax}(\\.\\d?)?|[0-9](\\.[0-9]?)?)$`);
}

function clamp(n: number, min: number, max: number): number {
  return Math.min(max, Math.max(min, n));
}

export function InterestRateInput({
  value,
  onChange,
  id,
  min = 0,
  max = 10,
  disabled = false,
  error = false,
  className,
}: InterestRateInputProps) {
  const [displayValue, setDisplayValue] = useState(() =>
    value > 0 ? String(value) : "",
  );
  const [focused, setFocused] = useState(false);

  const validationRegex = buildValidationRegex(max);

  // Sync when value changes externally
  useEffect(() => {
    if (!focused) {
      setDisplayValue(value > 0 ? String(value) : "");
    }
  }, [value, focused]);

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    const raw = e.target.value;
    // Allow empty string or values matching the pattern
    if (raw === "" || validationRegex.test(raw)) {
      setDisplayValue(raw);
    }
  }

  function handleFocus() {
    setFocused(true);
  }

  function handleBlur() {
    setFocused(false);
    // Strip trailing decimal point, then parse + clamp
    const cleaned = displayValue.replace(/\.$/, "");
    const parsed = parseFloat(cleaned);
    const final = isNaN(parsed) ? min : clamp(parsed, min, max);
    onChange(final);
    setDisplayValue(final > 0 ? String(final) : "");
  }

  return (
    <InputGroup
      className={cn(className)}
      data-disabled={disabled ? "true" : undefined}
    >
      <InputGroupInput
        id={id}
        type="text"
        inputMode="decimal"
        value={displayValue}
        onChange={handleChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        placeholder="0"
        disabled={disabled}
        aria-invalid={error ? "true" : undefined}
      />
      <InputGroupAddon align="inline-end">%</InputGroupAddon>
    </InputGroup>
  );
}
