/* ============================================================================
 * 서명전에 — TDS Switch 컴포넌트
 *  · 두 가지 상태(켜짐/꺼짐) 사이를 전환하는 단순 토글이에요.
 *    설정·옵션 ON/OFF 처럼 즉시 반영되는 boolean 상태를 다룰 때 써요.
 *
 *  · Checkbox(#129) 와의 차이
 *      Switch    — 켜짐/꺼짐 한 가지 동작이 즉시 반영 (예: 푸시 알림 ON/OFF)
 *      Checkbox  — 다중 선택 / 약관 동의 / 라디오 그룹 등 "선택" 상태 표시
 *
 *  · controlled / uncontrolled 모두 지원:
 *      controlled   — checked + onChange(event, checked)
 *      uncontrolled — defaultChecked + 내부 useState (편의 추가)
 *
 *  · props (TDS 스펙):
 *      checked         boolean — 현재 켜짐 여부 (controlled)
 *      defaultChecked  boolean — 초기 켜짐 여부 (uncontrolled, TDS 외 편의)
 *      disabled        boolean — 비활성 (기본 false)
 *      name            string  — 폼 전송용 input name
 *      hasTouchEffect  boolean — 누름 시 리플 + thumb 늘어남 (기본 true)
 *      onChange        (event: ChangeEvent<HTMLInputElement>, checked: boolean) => void
 *                      — 두 번째 인자가 다음 상태값. TDS 만의 시그니처.
 *      onClick         (event: MouseEvent) => void — 그대로 패스스루
 *      aria-label / aria-labelledby — 외부 레이블이 없을 때 반드시 권장
 *
 *  · 접근성:
 *      role="switch" + aria-checked={true|false} + aria-disabled (조건부)
 *      네이티브 <input type="checkbox"> 를 시각적으로 가리고 (visually-hidden)
 *      포커스/폼 전송/스크린 리더는 input 그대로 활용.
 *      외부 레이블에는 "스위치", "켜짐", "꺼짐" 같은 단어를 넣지 말고 기능만 적어요
 *      (예: aria-label="푸시 알림 받기").
 *
 *  · 모션:
 *      thumb translateX(0 ↔ 20px), 250ms cubic-bezier(0.4, 0, 0.2, 1).
 *      hasTouchEffect=true 면 누르는 동안 thumb 가로로 살짝 늘어나고
 *      손을 떼면 ripple 이 한 번 퍼져요.
 *      prefers-reduced-motion 시 모션은 모두 OFF.
 * ========================================================================== */

const { useState: __swUseState, useRef: __swUseRef, useCallback: __swUseCallback } = React;

function Switch({
  checked,
  defaultChecked,
  disabled = false,
  name,
  hasTouchEffect = true,
  onChange,
  onClick,
  className = "",
  style,
  id,
  "aria-label": ariaLabel,
  "aria-labelledby": ariaLabelledBy,
  ...rest
}) {
  // ----- controlled vs uncontrolled -----
  const isControlled = checked !== undefined;
  const [internalChecked, setInternalChecked] = __swUseState(!!defaultChecked);
  const currentChecked = isControlled ? !!checked : internalChecked;

  if (isControlled && typeof onChange !== "function") {
    if (window.console && console.warn) {
      console.warn(
        "[Switch] checked 만 주고 onChange 는 안 줬어요. " +
        "controlled 모드에서는 onChange(event, checked) 로 외부 상태를 갱신해야 해요."
      );
    }
  }

  // 접근성 라벨 안내 — 외부 라벨/aria-* 가 전혀 없으면 콘솔 경고
  if (
    !ariaLabel &&
    !ariaLabelledBy &&
    process.env.NODE_ENV !== "production" &&
    !rest["aria-describedby"]
  ) {
    // process 는 브라우저에 없을 수 있으니 try
    try {
      if (window.console && console.warn) {
        console.warn(
          "[Switch] aria-label 또는 aria-labelledby 를 권장해요. " +
          "스위치가 무엇을 토글하는지 스크린 리더가 안내할 라벨이 필요해요."
        );
      }
    } catch (_) { /* no-op */ }
  }

  // ----- 누름 시 리플 / stretch -----
  const [isPressed, setIsPressed] = __swUseState(false);
  const [rippleKey, setRippleKey] = __swUseState(0); // 매 클릭마다 새로 마운트해 리플 재생

  const handlePointerDown = function (e) {
    if (disabled) return;
    if (!hasTouchEffect) return;
    // 좌클릭 / 터치 / 펜만
    if (e.button !== undefined && e.button !== 0) return;
    setIsPressed(true);
  };

  const releasePress = function () {
    if (!hasTouchEffect) return;
    setIsPressed(false);
  };

  const handleInputChange = function (e) {
    if (disabled) return;
    const next = e.target.checked;
    if (!isControlled) setInternalChecked(next);
    if (typeof onChange === "function") {
      // ★ TDS 시그니처: (event, checked)
      onChange(e, next);
    }
    if (hasTouchEffect) {
      setRippleKey(function (k) { return k + 1; });
    }
  };

  const handleClick = function (e) {
    if (typeof onClick === "function") onClick(e);
  };

  // ----- 클래스 조립 -----
  const wrapCls = [
    "tds-switch",
    currentChecked ? "tds-switch--on" : "tds-switch--off",
    disabled ? "tds-switch--disabled" : "",
    hasTouchEffect ? "tds-switch--touch" : "tds-switch--no-touch",
    isPressed ? "is-pressed" : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  return (
    <label
      className={wrapCls}
      style={style}
      onClick={handleClick}
      onPointerDown={handlePointerDown}
      onPointerUp={releasePress}
      onPointerLeave={releasePress}
      onPointerCancel={releasePress}
    >
      <input
        type="checkbox"
        role="switch"
        className="tds-switch__input"
        id={id}
        name={name}
        checked={currentChecked}
        disabled={disabled}
        aria-checked={currentChecked}
        aria-disabled={disabled || undefined}
        aria-label={ariaLabel}
        aria-labelledby={ariaLabelledBy}
        onChange={handleInputChange}
        {...rest}
      />
      <span className="tds-switch__track" aria-hidden="true">
        <span className="tds-switch__thumb">
          {hasTouchEffect ? (
            // key 가 바뀌면 리플 노드가 새로 마운트되어 keyframe 처음부터 재생
            <span
              key={rippleKey}
              className="tds-switch__ripple"
              aria-hidden="true"
            />
          ) : null}
        </span>
      </span>
    </label>
  );
}

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