import React, { useEffect, useState } from 'react';

export const COMBO_CUSTOM = '__custom__';

interface Props {
  value: number;
  options: number[];
  min?: number;
  max?: number;
  allowDecimal?: boolean;
  onChange: (value: number) => void;
  /** true: 상단 입력창 항상 표시 + 하단 목록 선택 (조건대상 직접입력) */
  alwaysShowInput?: boolean;
  disabled?: boolean;
}

function sanitizeDraft(raw: string, allowDecimal: boolean): string {
  if (allowDecimal) {
    let s = raw.replace(/[^\d.-]/g, '');
    const minus = s.startsWith('-') ? '-' : '';
    s = s.replace(/-/g, '');
    const dot = s.indexOf('.');
    if (dot !== -1) {
      s = s.slice(0, dot + 1) + s.slice(dot + 1).replace(/\./g, '');
    }
    return minus + s;
  }
  return raw.replace(/\D/g, '');
}

function parseDraft(raw: string, allowDecimal: boolean): number | null {
  const trimmed = raw.trim();
  if (!trimmed || trimmed === '-' || trimmed === '.') return null;
  const n = allowDecimal ? parseFloat(trimmed) : parseInt(trimmed, 10);
  return Number.isFinite(n) ? n : null;
}

function clampValue(
  parsed: number,
  min: number,
  max: number,
  allowDecimal: boolean,
): number {
  return allowDecimal
    ? Math.max(min, Math.min(max, parsed))
    : Math.max(min, Math.min(max, Math.round(parsed)));
}

export default function ComboNumberInput({
  value,
  options,
  min = 1,
  max = 500,
  allowDecimal = false,
  onChange,
  alwaysShowInput = false,
  disabled = false,
}: Props) {
  const uniqueOptions = [...new Set(options)].sort((a, b) => a - b);
  const isPreset = uniqueOptions.includes(value);
  const [mode, setMode] = useState<'preset' | 'custom'>(() =>
    (alwaysShowInput || !isPreset) ? 'custom' : 'preset',
  );
  const [draft, setDraft] = useState(String(value));
  const [focused, setFocused] = useState(false);

  useEffect(() => {
    if (alwaysShowInput) {
      if (!focused) setDraft(String(value));
      return;
    }
    if (isPreset) {
      setMode('preset');
      if (!focused) setDraft(String(value));
    } else {
      setMode('custom');
      if (!focused) setDraft(String(value));
    }
  }, [value, isPreset, focused, alwaysShowInput]);

  const commitCustom = () => {
    const parsed = parseDraft(draft, allowDecimal);
    if (parsed == null) {
      setDraft(String(value));
      return;
    }
    const clamped = clampValue(parsed, min, max, allowDecimal);
    onChange(clamped);
    setDraft(String(clamped));
  };

  const handleSelect = (raw: string) => {
    if (raw === COMBO_CUSTOM) {
      if (!alwaysShowInput) setMode('custom');
      setDraft(String(value));
      return;
    }
    const n = allowDecimal ? parseFloat(raw) : parseInt(raw, 10);
    if (!Number.isFinite(n)) return;
    const clamped = clampValue(n, min, max, allowDecimal);
    if (!alwaysShowInput) setMode('preset');
    onChange(clamped);
    setDraft(String(clamped));
  };

  const showInput = alwaysShowInput || mode === 'custom';
  const selectValue = alwaysShowInput
    ? (isPreset ? String(value) : '')
    : (mode === 'custom' || !isPreset ? COMBO_CUSTOM : String(value));

  const inputEl = showInput ? (
    <input
      type="text"
      className="se-combo-num-input"
      inputMode={allowDecimal ? 'decimal' : 'numeric'}
      value={draft}
      placeholder="값 입력"
      disabled={disabled}
      onChange={e => setDraft(sanitizeDraft(e.target.value, allowDecimal))}
      onFocus={() => setFocused(true)}
      onBlur={() => {
        setFocused(false);
        commitCustom();
      }}
      onKeyDown={e => {
        if (e.key === 'Enter') {
          e.preventDefault();
          (e.target as HTMLInputElement).blur();
        }
      }}
      aria-label="직접 입력"
    />
  ) : null;

  return (
    <div className={`se-combo-num${alwaysShowInput ? ' se-combo-num--always-input' : ''}`}>
      {alwaysShowInput ? inputEl : null}
      <select
        className="se-combo-num-select sp-cond-sel"
        value={selectValue}
        disabled={disabled}
        onChange={e => handleSelect(e.target.value)}
        aria-label="목록에서 선택"
      >
        {alwaysShowInput && !isPreset && (
          <option value="" disabled>목록에서 선택</option>
        )}
        {uniqueOptions.map(opt => (
          <option key={opt} value={String(opt)}>{opt}</option>
        ))}
        {!alwaysShowInput && <option value={COMBO_CUSTOM}>직접입력</option>}
      </select>
      {!alwaysShowInput ? inputEl : null}
    </div>
  );
}
