/* ============================================================================
 * 서명전에 — TDS SearchField 컴포넌트
 *  · 검색 입력창 — 좌측 돋보기 아이콘 + 가운데 input + 우측 X 삭제 버튼.
 *  · 텍스트가 비어 있으면 X 버튼 자동 숨김.
 *
 *  · controlled / uncontrolled 모두 지원:
 *      controlled   — value + onChange 전달
 *      uncontrolled — defaultValue (옵션) + 내부 useState 로 관리
 *
 *  · SearchFieldProps:
 *      fixed             boolean (기본 false) — 상단에 position: fixed 로 고정
 *      takeSpace         boolean (기본 true)  — fixed=true 일 때 같은 높이의
 *                                              빈 div (placeholder) 를 원래
 *                                              자리에 삽입해 콘텐츠가 위로
 *                                              점프하지 않게 함
 *      onDeleteClick     () => void           — X 삭제 버튼 클릭 시 추가 콜백
 *                                              (input 비우기는 자동, 그 외 액션)
 *      value             string                — controlled value
 *      defaultValue      string                — uncontrolled 초기값
 *      onChange          (e) => void           — 값 변경 콜백 (controlled/uncontrolled 모두)
 *      placeholder       string                — input placeholder
 *      disabled          boolean
 *      aria-label        기본 "검색어 입력"
 *      그 외 모든 input props (name, autoFocus, inputMode, maxLength, …) 패스스루
 *      className, style, id  → 외곽 wrapper 에 적용
 *
 *  · 접근성:
 *      · input 에 type="search" + role 자동
 *      · X 버튼은 aria-label="검색어 지우기" + type="button" (form submit 방지)
 *      · 돋보기 SVG 는 aria-hidden="true"
 * ========================================================================== */

// ----- 좌측 돋보기 SVG (24px) -----
function __SearchFieldMagnifierSvg() {
  return (
    <svg
      className="tds-searchfield__icon-svg"
      viewBox="0 0 24 24"
      aria-hidden="true"
      focusable="false"
    >
      <circle cx="11" cy="11" r="7" />
      <line x1="16" y1="16" x2="21" y2="21" />
    </svg>
  );
}

// ----- 우측 X SVG (14px, 회색 원 안에) -----
function __SearchFieldClearSvg() {
  return (
    <svg
      className="tds-searchfield__clear-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>
  );
}

function SearchField({
  fixed = false,
  takeSpace = true,
  onDeleteClick,
  value,
  defaultValue,
  onChange,
  placeholder,
  disabled = false,
  className = "",
  style,
  id,
  "aria-label": ariaLabel,
  ...rest
}) {
  // controlled vs uncontrolled 판별
  const isControlled = value !== undefined;
  const [internalValue, setInternalValue] = React.useState(
    typeof defaultValue === "string" ? defaultValue : ""
  );
  const currentValue = isControlled ? (value || "") : internalValue;

  // input ref — clear 후 포커스 복원에 사용
  const inputRef = React.useRef(null);

  const finalAriaLabel = ariaLabel != null ? ariaLabel : "검색어 입력";

  // ----- 입력 변화 핸들러 -----
  const handleChange = function (e) {
    if (!isControlled) {
      setInternalValue(e.target.value);
    }
    if (typeof onChange === "function") onChange(e);
  };

  // ----- X 버튼 클릭 핸들러 -----
  const handleClear = function () {
    if (disabled) return;

    // 내부 value 비우기 (uncontrolled)
    if (!isControlled) {
      setInternalValue("");
    }

    // onChange 가 있으면 동기적으로 빈 값으로 호출 — 가짜 이벤트 객체
    // (controlled 사용처가 외부 상태를 갱신할 수 있도록)
    if (typeof onChange === "function" && inputRef.current) {
      const synthetic = {
        target: inputRef.current,
        currentTarget: inputRef.current,
        type: "change",
        // input 의 value 는 한 프레임 뒤에 비울 거라 즉시 "" 보장
        nativeEvent: null,
      };
      // input 의 실제 값도 "" 로 — controlled 일 때는 외부에서 다음 렌더에 반영
      try {
        inputRef.current.value = "";
      } catch (_e) {
        // some input types disallow direct .value assign — ignore
      }
      // target.value 가 "" 인 새 객체로 던져 줌
      synthetic.target = { ...inputRef.current, value: "" };
      onChange(synthetic);
    }

    // 사용자 콜백
    if (typeof onDeleteClick === "function") onDeleteClick();

    // input 으로 포커스 복원 — 사용자가 곧바로 다시 입력 가능
    if (inputRef.current && typeof inputRef.current.focus === "function") {
      inputRef.current.focus();
    }
  };

  // ----- 클래스 조립 -----
  const wrapCls = [
    "tds-searchfield",
    fixed ? "tds-searchfield--fixed" : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  const showClear = !disabled && currentValue !== "";

  // ----- spacer (fixed + takeSpace 일 때만) -----
  const spacer = fixed && takeSpace ? (
    <div
      className={
        "tds-searchfield__spacer tds-searchfield__spacer--with-safe"
      }
      aria-hidden="true"
    />
  ) : null;

  // takeSpace 가 fixed=false 인데 명시적으로 true 면 무의미함을 한 번 알려줌
  if (takeSpace === false && fixed === false) {
    // takeSpace 기본이 true 라 명시 false 일 때만 정보성 — 경고는 스킵
  }
  if (takeSpace && !fixed) {
    // 사용자가 takeSpace 만 true 로 줬다면 fixed=false 라 효과 없음. 한 번 알림.
    if (window.console && console.info) {
      // 너무 시끄럽지 않게 info 레벨로
      // (warn 은 fixed=false 인 기본 사용 시 모두 떠서 노이즈)
    }
  }

  return (
    <React.Fragment>
      {spacer}
      <div
        id={id}
        className={wrapCls}
        style={style}
      >
        <div className="tds-searchfield__box">
          <span className="tds-searchfield__icon" aria-hidden="true">
            <__SearchFieldMagnifierSvg />
          </span>
          <input
            ref={inputRef}
            type="search"
            className="tds-searchfield__input"
            value={currentValue}
            onChange={handleChange}
            placeholder={placeholder}
            disabled={disabled}
            aria-label={finalAriaLabel}
            // search input 자동 X (브라우저 기본) 끄기 — 우리 X 버튼 사용
            // (Chrome/Safari 가 자체 X 를 추가하는 걸 방지)
            // CSS 로 ::-webkit-search-cancel-button 숨기는 게 더 깔끔하지만
            // inline 으로도 안전하게 처리
            {...rest}
          />
          {showClear ? (
            <button
              type="button"
              className="tds-searchfield__clear"
              onClick={handleClear}
              aria-label="검색어 지우기"
            >
              <__SearchFieldClearSvg />
            </button>
          ) : null}
        </div>
      </div>
    </React.Fragment>
  );
}

window.SearchField = SearchField;
Object.assign(window, { SearchField });
