"use client";

import * as React from "react";
import { DeleteIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

/**
 * Passcode entry: dots fill as digits are keyed on the on-screen keypad, or typed on a keyboard while the
 * pad has focus (digits and Backspace). `onComplete` fires once all digits are in; remount with a new `key`
 * to clear it after a wrong code.
 */
export function PasscodeInput({
  length = 4,
  error,
  disabled,
  defaultValue = "",
  label = "Passcode",
  autoFocus,
  onChange,
  onComplete,
}: {
  length?: number;
  error?: string;
  disabled?: boolean;
  defaultValue?: string;
  label?: string;
  autoFocus?: boolean;
  onChange?: (value: string) => void;
  onComplete?: (value: string) => void;
}) {
  const [value, setValue] = React.useState(defaultValue);
  const ref = React.useRef<HTMLDivElement>(null);

  React.useEffect(() => {
    if (autoFocus) ref.current?.focus();
  }, [autoFocus]);

  const update = (next: string) => {
    if (next === value) return;
    setValue(next);
    onChange?.(next);
    if (next.length === length) onComplete?.(next);
  };
  const press = (d: string) => value.length < length && update(value + d);
  const back = () => value.length && update(value.slice(0, -1));

  return (
    <div
      ref={ref}
      tabIndex={disabled ? -1 : 0}
      role="group"
      aria-label={`${label}, ${value.length} of ${length} digits entered`}
      onKeyDown={(e) => {
        if (disabled) return;
        if (/^[0-9]$/.test(e.key)) {
          e.preventDefault();
          press(e.key);
        } else if (e.key === "Backspace") {
          e.preventDefault();
          back();
        }
      }}
      className="mx-auto w-56 space-y-3 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-4"
    >
      <div className="flex justify-center gap-3" aria-hidden>
        {Array.from({ length }, (_, i) => (
          <span
            key={i}
            className={cn("size-3.5 rounded-full border", i < value.length ? (error ? "border-destructive bg-destructive" : "border-primary bg-primary") : "border-input bg-background")}
          />
        ))}
      </div>
      <p className="h-4 text-center text-xs text-destructive" role={error ? "alert" : undefined}>
        {error}
      </p>
      <div className="grid grid-cols-3 gap-2">
        {["1", "2", "3", "4", "5", "6", "7", "8", "9"].map((d) => (
          <Button key={d} variant="outline" className="h-11 text-base tabular-nums" disabled={disabled} tabIndex={-1} onClick={() => press(d)}>
            {d}
          </Button>
        ))}
        <span />
        <Button variant="outline" className="h-11 text-base tabular-nums" disabled={disabled} tabIndex={-1} onClick={() => press("0")}>
          0
        </Button>
        <Button variant="ghost" className="h-11" aria-label="Delete last digit" disabled={disabled || value.length === 0} tabIndex={-1} onClick={back}>
          <DeleteIcon />
        </Button>
      </div>
    </div>
  );
}
