"use client";

import * as React from "react";
import { cn } from "@/lib/utils";
import { formatNumber, removeLeadingZeros } from "@/lib/formatters";

export interface CurrencyInputProps
  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "type"> {
  value: number | string | undefined;
  onChange: (value: number | undefined) => void;
  error?: boolean;
  /** 통화 기호 (기본: ₩) */
  currency?: "₩" | "$" | "¥" | "€";
  /** 통화 기호 표시 (기본: true) */
  showCurrency?: boolean;
  /** 음수 허용 (기본: false) */
  allowNegative?: boolean;
  /** 빈 값 허용 (기본: true) */
  allowEmpty?: boolean;
}

/**
 * CurrencyInput - 금액 입력 전용 컴포넌트
 *
 * 특징:
 * - 입력 중에도 실시간 천단위 콤마 표시
 * - 정수만 허용 (소수점 없음)
 * - 통화 기호 표시 (₩, $, ¥, €)
 * - Leading zero 자동 제거
 * - 커서 위치 자동 보정
 *
 * @example
 * // 기본 (원화)
 * <CurrencyInput value={price} onChange={setPrice} />
 *
 * // 달러
 * <CurrencyInput value={usdPrice} onChange={setUsdPrice} currency="$" />
 *
 * // 음수 허용 (환불 등)
 * <CurrencyInput value={refund} onChange={setRefund} allowNegative />
 */
const CurrencyInput = React.forwardRef<HTMLInputElement, CurrencyInputProps>(
  (
    {
      className,
      value,
      onChange,
      error,
      currency = "₩",
      showCurrency = true,
      allowNegative = false,
      allowEmpty = true,
      onFocus,
      onBlur,
      ...props
    },
    ref
  ) => {
    const [isFocused, setIsFocused] = React.useState(false);
    const [displayValue, setDisplayValue] = React.useState<string>("");
    const innerRef = React.useRef<HTMLInputElement>(null);
    const cursorPosRef = React.useRef<number | null>(null);

    // 외부 ref와 내부 ref 결합
    const combinedRef = React.useCallback(
      (node: HTMLInputElement | null) => {
        innerRef.current = node;
        if (typeof ref === 'function') ref(node);
        else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;
      },
      [ref]
    );

    // 렌더 후 커서 위치 복원
    React.useLayoutEffect(() => {
      if (cursorPosRef.current !== null && innerRef.current && isFocused) {
        innerRef.current.setSelectionRange(cursorPosRef.current, cursorPosRef.current);
        cursorPosRef.current = null;
      }
    });

    // 숫자를 콤마 포맷 문자열로 변환
    const formatWithCommas = (sanitized: string): string => {
      if (!sanitized || sanitized === "-") return sanitized || "";
      const isNeg = sanitized.startsWith("-");
      const digits = isNeg ? sanitized.slice(1) : sanitized;
      if (!digits) return sanitized;
      const num = parseInt(digits, 10);
      if (isNaN(num)) return "";
      const formatted = formatNumber(num, { useComma: true });
      return isNeg ? `-${formatted}` : formatted;
    };

    // 외부 value 변경 시 displayValue 동기화
    React.useEffect(() => {
      if (!isFocused) {
        if (value === undefined || value === null || value === "") {
          setDisplayValue("");
        } else {
          const numValue = typeof value === "string" ? parseFloat(value) : value;
          if (!isNaN(numValue)) {
            setDisplayValue(formatNumber(numValue, { useComma: true }));
          } else {
            setDisplayValue("");
          }
        }
      }
    }, [value, isFocused]);

    // 입력값 정제
    const sanitizeInput = (input: string): string => {
      let result = input;

      // 숫자와 음수 기호만 허용
      if (allowNegative) {
        result = result.replace(/[^\d-]/g, "");
        // 음수 기호는 맨 앞에만
        if (result.includes("-")) {
          const isNegative = result.startsWith("-");
          result = result.replace(/-/g, "");
          if (isNegative) result = "-" + result;
        }
      } else {
        result = result.replace(/\D/g, "");
      }

      // Leading zero 제거
      if (result) {
        result = removeLeadingZeros(result);
      }

      return result;
    };

    // 값을 숫자로 변환
    const parseValue = (input: string): number | undefined => {
      if (!input || input === "-") {
        return allowEmpty ? undefined : 0;
      }

      const num = parseInt(input, 10);
      return isNaN(num) ? (allowEmpty ? undefined : 0) : num;
    };

    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      const rawValue = e.target.value;
      const cursorPos = e.target.selectionStart || 0;

      // 커서 앞 숫자 개수 계산 (콤마 무시)
      const digitsBeforeCursor = rawValue.slice(0, cursorPos).replace(/[^\d]/g, "").length;

      // 콤마 제거 후 정제
      const withoutComma = rawValue.replace(/,/g, "");
      const sanitized = sanitizeInput(withoutComma);

      if (sanitized === "-") {
        setDisplayValue(sanitized);
        cursorPosRef.current = 1;
        return;
      }

      const numValue = parseValue(sanitized);
      onChange(numValue);

      // 실시간 콤마 포맷
      const formatted = formatWithCommas(sanitized);
      setDisplayValue(formatted);

      // 새 커서 위치 계산: 숫자 개수 기준으로 위치 복원
      let digitCount = 0;
      let newPos = formatted.length;
      for (let i = 0; i < formatted.length; i++) {
        if (/\d/.test(formatted[i])) {
          digitCount++;
        }
        if (digitCount === digitsBeforeCursor) {
          newPos = i + 1;
          break;
        }
      }
      cursorPosRef.current = newPos;
    };

    const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
      setIsFocused(true);
      // 포커스 시에도 콤마 유지 (실시간 포맷)
      onFocus?.(e);
    };

    const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
      setIsFocused(false);

      const sanitized = sanitizeInput(displayValue.replace(/,/g, ""));
      const numValue = parseValue(sanitized);

      onChange(numValue);

      // 포맷팅된 값으로 표시
      if (numValue !== undefined) {
        setDisplayValue(formatNumber(numValue, { useComma: true }));
      } else {
        setDisplayValue("");
      }

      onBlur?.(e);
    };

    const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
      const allowedKeys = [
        "Backspace", "Delete", "Tab", "Escape", "Enter",
        "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown",
        "Home", "End"
      ];

      if (allowedKeys.includes(e.key)) return;

      // Ctrl/Cmd + A, C, V, X 허용
      if ((e.ctrlKey || e.metaKey) && ["a", "c", "v", "x"].includes(e.key.toLowerCase())) {
        return;
      }

      // 숫자 허용
      if (/^\d$/.test(e.key)) return;

      // 음수 허용 (맨 앞에만)
      if (allowNegative && e.key === "-" && !displayValue.includes("-")) {
        const input = e.target as HTMLInputElement;
        if (input.selectionStart === 0) return;
      }

      e.preventDefault();
    };

    return (
      <div className="relative">
        {/* 통화 기호 (왼쪽) */}
        {showCurrency && (
          <span className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm pointer-events-none">
            {currency}
          </span>
        )}
        <input
          type="text"
          inputMode="numeric"
          ref={combinedRef}
          data-slot="input"
          className={cn(
            "file:text-foreground placeholder:text-muted-foreground/50 selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base bg-input-background transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
            "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
            error && "border-red-500 focus-visible:border-red-500 focus-visible:ring-red-500/20",
            showCurrency && "pl-8",
            className
          )}
          value={displayValue}
          onChange={handleChange}
          onFocus={handleFocus}
          onBlur={handleBlur}
          onKeyDown={handleKeyDown}
          {...props}
        />
      </div>
    );
  }
);

CurrencyInput.displayName = "CurrencyInput";

export { CurrencyInput };
