/* ============================================================================
 * 서명전에 — TDS TextField 컴포넌트 (Task #167)
 *
 *  · 텍스트 입력의 표준 진입점. label / placeholder / help 한 묶음을 관리.
 *  · 4 가지 변종(variant): box · line · big · hero
 *  · 라벨 표시 옵션(labelOption): "appear" (값/포커스 시에만) · "sustain" (항상)
 *  · prefix / suffix : 텍스트 addon (예: "원", "@gmail.com")
 *  · right           : 임의 ReactNode 슬롯 (Clearable / Password / Button 이 자체적으로 채움)
 *  · hasError + handleError : 에러 상태 + 에러 문구
 *  · disabled        : 입력 차단 + 시각적 회색 처리
 *  · format.transform / format.reset : 입력값 포매팅 함수 (예: "1000000" → "1,000,000")
 *  · paddingTop / paddingBottom : 외곽 여백 커스텀
 *  · controlled (value+onChange) / uncontrolled (defaultValue) 모두 지원
 *
 *  · 서브 컴포넌트:
 *      TextField.Clearable  — 우측 X 버튼 자동 (값 비어있을 땐 숨김)
 *      TextField.Password   — type="password" + 눈 토글 버튼
 *      TextField.Button     — input 대신 button 처럼 동작 (피커 진입용 — 예: 날짜 선택)
 *
 *  · 디자인 토큰:
 *      box  높이 52 / 둥글기 14 / 회색100 배경 / 포커스 시 ring
 *      line 하단 1.5px 라인 / 포커스 시 brand 라인
 *      big  높이 64 / 라벨 굵게 / input ty-4 굵게
 *      hero 박스 없음 / input ty-2 bold + tnum (금액 입력)
 *
 *  · Babel Standalone 환경 호환:
 *      React.* 훅을 직접 호출하지 않고 __tfUseState 등 alias 로 호출.
 *      (다른 스크립트의 동일 이름 변수와 충돌 회피)
 * ========================================================================== */

// ----- React 훅 alias (Babel Standalone 충돌 방지) -----
const __tfUseState           = (typeof React !== "undefined" && React.useState) || function (v) { return [v, function () {}]; };
const __tfUseRef             = (typeof React !== "undefined" && React.useRef) || function () { return { current: null }; };
const __tfUseEffect          = (typeof React !== "undefined" && React.useEffect) || function () {};
const __tfUseCallback        = (typeof React !== "undefined" && React.useCallback) || function (fn) { return fn; };
const __tfUseMemo            = (typeof React !== "undefined" && React.useMemo) || function (fn) { return fn(); };
const __tfForwardRef         = (typeof React !== "undefined" && React.forwardRef) || function (fn) { return fn; };
const __tfUseImperativeHandle= (typeof React !== "undefined" && React.useImperativeHandle) || function () {};

// ----- 클래스 조립 헬퍼 -----
function __tfJoin() {
  let out = "";
  for (let i = 0; i < arguments.length; i++) {
    const v = arguments[i];
    if (!v) continue;
    out = out ? out + " " + v : v;
  }
  return out;
}

// ----- enum 가드 -----
function __tfEnum(value, allowed, fallback, propPath) {
  if (allowed.indexOf(value) !== -1) return value;
  if (value !== undefined && window.console && console.warn) {
    console.warn("[TextField] " + propPath + " 값이 잘못됨: " + JSON.stringify(value) + ". 허용: " + allowed.join(", ") + ". 기본 " + fallback + " 사용.");
  }
  return fallback;
}

// ----- X SVG -----
function __tfClearSvg() {
  return (
    <svg viewBox="0 0 14 14" aria-hidden="true" focusable="false">
      <line x1="3" y1="3" x2="11" y2="11" />
      <line x1="11" y1="3" x2="3" y2="11" />
    </svg>
  );
}

// ----- 눈(보임) SVG -----
function __tfEyeOpenSvg() {
  return (
    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
      <path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" />
      <circle cx="12" cy="12" r="3" />
    </svg>
  );
}

// ----- 눈(가림) SVG -----
function __tfEyeOffSvg() {
  return (
    <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
      <path d="M2 12s3.5-7 10-7c2 0 3.7.6 5.2 1.4" />
      <path d="M22 12s-3.5 7-10 7c-2 0-3.7-.6-5.2-1.4" />
      <path d="M9.6 9.6a3 3 0 0 0 4.2 4.2" />
      <line x1="3" y1="3" x2="21" y2="21" />
    </svg>
  );
}

// ----- 화살표 SVG (TextField.Button 의 기본 chevron) -----
function __tfChevronSvg() {
  return (
    <svg viewBox="0 0 20 20" aria-hidden="true" focusable="false">
      <polyline points="7 5 13 10 7 15" />
    </svg>
  );
}

/* ----------------------------------------------------------------------------
 * TextField (root) — forwardRef
 *   ref API:
 *     focus()  — input 으로 포커스
 *     blur()   — 포커스 해제
 *     clear()  — 값 비우기 + onChange 호출
 *     el()     — 내부 input DOM 반환
 * -------------------------------------------------------------------------- */
const TextField = __tfForwardRef(function TextField(props, ref) {
  const {
    // 기본 props
    label,
    placeholder = "",
    help,
    variant: variantProp,
    labelOption: labelOptionProp,
    hasError = false,
    handleError,
    disabled = false,
    required = false,

    // 슬롯
    prefix,
    suffix,
    right,

    // 값 / 콜백
    value,
    defaultValue,
    onChange,
    onFocus,
    onBlur,

    // 포매팅
    format,

    // 입력 type — 기본 "text"
    type = "text",

    // 외곽 여백
    paddingTop,
    paddingBottom,

    // 외부에서 변종 강제 (서브 컴포넌트가 사용)
    __subRight,

    // 패스스루
    className = "",
    style,
    id,
    name,
    autoFocus,
    autoComplete,
    inputMode,
    maxLength,
    "aria-label": ariaLabel,

    ...rest
  } = props;

  const variant = __tfEnum(variantProp, ["box", "line", "big", "hero"], "box", "variant");
  const labelOption = __tfEnum(labelOptionProp, ["appear", "sustain"], "sustain", "labelOption");

  // ----- controlled / uncontrolled -----
  const isControlled = value !== undefined;
  const [internalValue, setInternalValue] = __tfUseState(typeof defaultValue === "string" ? defaultValue : "");
  const rawValue = isControlled ? (value == null ? "" : String(value)) : internalValue;

  // ----- 포매팅된 표시값 -----
  const displayValue = __tfUseMemo(function () {
    if (format && typeof format.transform === "function") {
      try {
        return format.transform(rawValue);
      } catch (_e) {
        return rawValue;
      }
    }
    return rawValue;
  }, [rawValue, format]);

  // ----- 포커스 상태 -----
  const [focused, setFocused] = __tfUseState(false);

  // ----- ref -----
  const inputRef = __tfUseRef(null);

  __tfUseImperativeHandle(ref, function () {
    return {
      focus: function () { if (inputRef.current && inputRef.current.focus) inputRef.current.focus(); },
      blur:  function () { if (inputRef.current && inputRef.current.blur)  inputRef.current.blur(); },
      clear: function () { __tfApplyChange(""); },
      el:    function () { return inputRef.current; },
    };
  }, [isControlled]);

  // ----- 값 적용 헬퍼 -----
  function __tfApplyChange(nextRaw) {
    let nv = nextRaw;
    // format.reset 이 있으면 표시값 → 원시값 복원
    if (format && typeof format.reset === "function") {
      try { nv = format.reset(nextRaw); } catch (_e) { nv = nextRaw; }
    }
    if (!isControlled) setInternalValue(nv);
    if (typeof onChange === "function") {
      const synthetic = {
        target: { value: nv, name: name },
        currentTarget: inputRef.current,
        type: "change",
      };
      onChange(synthetic);
    }
  }

  // ----- 핸들러 -----
  const handleInputChange = function (e) {
    __tfApplyChange(e.target.value);
  };
  const handleFocus = function (e) {
    setFocused(true);
    if (typeof onFocus === "function") onFocus(e);
  };
  const handleBlur = function (e) {
    setFocused(false);
    if (typeof onBlur === "function") onBlur(e);
  };

  // ----- label visibility (appear 모드) -----
  const hasValueOrFocus = focused || (rawValue && rawValue.length > 0);
  const labelShown = labelOption === "sustain" || (labelOption === "appear" && hasValueOrFocus);

  // ----- 클래스 -----
  const rootCls = __tfJoin(
    "tds-tf",
    "tds-tf--" + variant,
    "tds-tf--" + labelOption,
    labelShown ? "tds-tf--shown" : "",
    focused ? "tds-tf--focused" : "",
    hasError ? "tds-tf--error" : "",
    disabled ? "tds-tf--disabled" : "",
    className
  );

  // ----- 스타일 (paddingTop/Bottom) -----
  const finalStyle = Object.assign({}, style || {});
  if (paddingTop != null) finalStyle.paddingTop = typeof paddingTop === "number" ? paddingTop + "px" : paddingTop;
  if (paddingBottom != null) finalStyle.paddingBottom = typeof paddingBottom === "number" ? paddingBottom + "px" : paddingBottom;

  // ----- 본체 -----
  return (
    <div id={id} className={rootCls} style={finalStyle}>
      {label != null && label !== "" ? (
        <label className="tds-tf__label" htmlFor={id ? id + "__input" : undefined}>
          {label}
          {required ? <span className="tds-tf__label-required" aria-hidden="true">*</span> : null}
        </label>
      ) : null}

      <div className="tds-tf__body">
        {prefix != null ? <span className="tds-tf__prefix">{prefix}</span> : null}

        <input
          ref={inputRef}
          id={id ? id + "__input" : undefined}
          name={name}
          type={type}
          className="tds-tf__input"
          value={displayValue}
          onChange={handleInputChange}
          onFocus={handleFocus}
          onBlur={handleBlur}
          placeholder={placeholder}
          disabled={disabled}
          autoFocus={autoFocus}
          autoComplete={autoComplete}
          inputMode={inputMode}
          maxLength={maxLength}
          aria-label={ariaLabel || label || undefined}
          aria-invalid={hasError ? "true" : undefined}
          aria-describedby={(handleError || help) && id ? id + "__help" : undefined}
          required={required}
          {...rest}
        />

        {suffix != null ? <span className="tds-tf__suffix">{suffix}</span> : null}

        {right != null || __subRight != null ? (
          <span className="tds-tf__right">
            {__subRight != null ? __subRight : right}
          </span>
        ) : null}
      </div>

      {(hasError && handleError) || help ? (
        <p
          id={id ? id + "__help" : undefined}
          className="tds-tf__help"
          role={hasError ? "alert" : undefined}
        >
          {hasError && handleError ? handleError : help}
        </p>
      ) : null}
    </div>
  );
});

/* ----------------------------------------------------------------------------
 * TextField.Clearable — 우측 X 버튼 자동 (값 있을 때만)
 *   onClear?: () => void  — X 클릭 시 추가 콜백
 * -------------------------------------------------------------------------- */
const TextFieldClearable = __tfForwardRef(function TextFieldClearable(props, ref) {
  const { onClear, value, defaultValue, onChange, disabled, ...rest } = props;

  const isControlled = value !== undefined;
  const [internalValue, setInternalValue] = __tfUseState(typeof defaultValue === "string" ? defaultValue : "");
  const currentValue = isControlled ? (value == null ? "" : String(value)) : internalValue;

  const innerRef = __tfUseRef(null);
  __tfUseImperativeHandle(ref, function () { return innerRef.current; }, []);

  const handleChange = function (e) {
    if (!isControlled) setInternalValue(e.target.value);
    if (typeof onChange === "function") onChange(e);
  };

  const handleClickClear = function () {
    if (disabled) return;
    if (!isControlled) setInternalValue("");
    if (typeof onChange === "function") {
      onChange({
        target: { value: "", name: rest.name },
        currentTarget: innerRef.current && innerRef.current.el ? innerRef.current.el() : null,
        type: "change",
      });
    }
    if (typeof onClear === "function") onClear();
    if (innerRef.current && typeof innerRef.current.focus === "function") {
      innerRef.current.focus();
    }
  };

  const showClear = !disabled && currentValue && currentValue.length > 0;

  const clearBtn = showClear ? (
    <button
      type="button"
      className="tds-tf__clear"
      onClick={handleClickClear}
      aria-label="입력 지우기"
    >
      <__tfClearSvg />
    </button>
  ) : null;

  return (
    <TextField
      ref={innerRef}
      value={isControlled ? currentValue : undefined}
      defaultValue={!isControlled ? currentValue : undefined}
      onChange={handleChange}
      disabled={disabled}
      __subRight={clearBtn}
      {...rest}
    />
  );
});

/* ----------------------------------------------------------------------------
 * TextField.Password — type="password" + 눈 토글
 *   onVisibilityChange?: (visible: boolean) => void
 * -------------------------------------------------------------------------- */
const TextFieldPassword = __tfForwardRef(function TextFieldPassword(props, ref) {
  const { onVisibilityChange, type: _ignoredType, disabled, ...rest } = props;
  const [visible, setVisible] = __tfUseState(false);

  const innerRef = __tfUseRef(null);
  __tfUseImperativeHandle(ref, function () { return innerRef.current; }, []);

  const handleToggle = function () {
    if (disabled) return;
    const next = !visible;
    setVisible(next);
    if (typeof onVisibilityChange === "function") onVisibilityChange(next);
    // 토글 후 input 으로 포커스 복원 (커서 위치 유지를 위해 다음 프레임)
    setTimeout(function () {
      if (innerRef.current && typeof innerRef.current.focus === "function") {
        innerRef.current.focus();
      }
    }, 0);
  };

  const eyeBtn = (
    <button
      type="button"
      className="tds-tf__eye"
      onClick={handleToggle}
      aria-label={visible ? "비밀번호 가리기" : "비밀번호 보이기"}
      aria-pressed={visible ? "true" : "false"}
      disabled={disabled}
    >
      {visible ? <__tfEyeOffSvg /> : <__tfEyeOpenSvg />}
    </button>
  );

  return (
    <TextField
      ref={innerRef}
      type={visible ? "text" : "password"}
      autoComplete={rest.autoComplete || "current-password"}
      disabled={disabled}
      __subRight={eyeBtn}
      {...rest}
    />
  );
});

/* ----------------------------------------------------------------------------
 * TextField.Button — input 대신 button 처럼 동작
 *   value 는 표시 텍스트로만 사용 (편집 불가).
 *   onClick 으로 외부 피커(BottomSheet 등) 트리거.
 * -------------------------------------------------------------------------- */
function TextFieldButton(props) {
  const {
    label,
    placeholder = "",
    help,
    variant: variantProp,
    labelOption: labelOptionProp,
    hasError = false,
    handleError,
    disabled = false,
    required = false,
    prefix,
    suffix,
    right,
    value,
    onClick,
    paddingTop,
    paddingBottom,
    className = "",
    style,
    id,
    "aria-label": ariaLabel,
    ...rest
  } = props;

  const variant = __tfEnum(variantProp, ["box", "line", "big", "hero"], "box", "variant");
  const labelOption = __tfEnum(labelOptionProp, ["appear", "sustain"], "sustain", "labelOption");

  const hasValue = value != null && String(value).length > 0;
  const labelShown = labelOption === "sustain" || (labelOption === "appear" && hasValue);

  const rootCls = __tfJoin(
    "tds-tf",
    "tds-tf--" + variant,
    "tds-tf--" + labelOption,
    labelShown ? "tds-tf--shown" : "",
    hasError ? "tds-tf--error" : "",
    disabled ? "tds-tf--disabled" : "",
    className
  );

  const finalStyle = Object.assign({}, style || {});
  if (paddingTop != null) finalStyle.paddingTop = typeof paddingTop === "number" ? paddingTop + "px" : paddingTop;
  if (paddingBottom != null) finalStyle.paddingBottom = typeof paddingBottom === "number" ? paddingBottom + "px" : paddingBottom;

  const handleKeyDown = function (e) {
    if (disabled) return;
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      if (typeof onClick === "function") onClick(e);
    }
  };

  return (
    <div id={id} className={rootCls} style={finalStyle}>
      {label != null && label !== "" ? (
        <span className="tds-tf__label">
          {label}
          {required ? <span className="tds-tf__label-required" aria-hidden="true">*</span> : null}
        </span>
      ) : null}

      <button
        type="button"
        className="tds-tf__body tds-tf__body--button"
        onClick={onClick}
        onKeyDown={handleKeyDown}
        disabled={disabled}
        aria-label={ariaLabel || label || undefined}
        aria-invalid={hasError ? "true" : undefined}
        {...rest}
      >
        {prefix != null ? <span className="tds-tf__prefix">{prefix}</span> : null}

        <span
          className="tds-tf__input"
          style={{
            display: "inline-flex",
            alignItems: "center",
            textAlign: "left",
            color: hasValue ? undefined : "var(--label-tertiary, #8b95a1)",
            fontWeight: hasValue ? undefined : "var(--w-regular, 400)",
          }}
        >
          {hasValue ? value : placeholder}
        </span>

        {suffix != null ? <span className="tds-tf__suffix">{suffix}</span> : null}

        <span className="tds-tf__right">
          {right != null ? right : (
            <span className="tds-tf__chevron" aria-hidden="true">
              <__tfChevronSvg />
            </span>
          )}
        </span>
      </button>

      {(hasError && handleError) || help ? (
        <p
          className="tds-tf__help"
          role={hasError ? "alert" : undefined}
        >
          {hasError && handleError ? handleError : help}
        </p>
      ) : null}
    </div>
  );
}

// ----- 서브 컴포넌트 부착 -----
TextField.Clearable = TextFieldClearable;
TextField.Password = TextFieldPassword;
TextField.Button = TextFieldButton;

// ----- window 등록 -----
window.TextField = TextField;
Object.assign(window, { TextField });
