/* ============================================================================
 * 서명전에 — TDS FullSecureKeypad 컴포넌트
 *  · 비밀번호·계정 로그인처럼 보안이 중요한 입력을 받을 때 쓰는 풀 키패드.
 *    숫자(1~0) + QWERTY 알파벳 + 한글 듀얼 라벨 + 하단 특수/Space/입력 완료.
 *
 *  · 보안 특성:
 *      1. **랜덤 빈 셀** — 알파벳 자리 사이에 일부 빈 셀이 섞여 들어가요.
 *         어깨너머로 지켜보는 제3자가 키 위치만 외우기 어렵게 해요.
 *         ref.reorderEmptyCells() 로 재셔플 가능.
 *      2. **대소문자 토글** — Shift 키로 대문자/소문자 전환.
 *      3. **한글 동반 표시** — 한국어 사용자가 영문 키보드 자판을 한글로
 *         떠올리지 않아도 되게, `q(ㅂ)` 처럼 각 알파벳 옆에 한글을 작게 병기.
 *
 *  · ref 노출:
 *      reorderEmptyCells(): void   — 빈 셀 위치를 새로 섞어요.
 *      element: HTMLDivElement | null — 루트 DOM 노드 (포커스/스크롤 제어용).
 *
 *  · props (FullSecureKeypadProps):
 *      onKeyClick*          (value: string) => void  — 알파벳/숫자 키
 *                           (대문자 여부는 호출 시점 shift 상태 반영)
 *      onBackspaceClick*    () => void   — 지우기
 *      onSpaceClick*        () => void   — Space
 *      onSubmit*            () => void   — "입력 완료"
 *      submitDisabled?      boolean                  — 기본 false
 *      submitButtonText?    string                   — 기본 "입력 완료"
 *      backspaceAriaLabel?  string                   — 기본 "한 글자 지우기"
 *      spaceAriaLabel?      string                   — 기본 "띄어쓰기"
 *      specialAriaLabel?    string                   — 기본 "특수문자"
 *      onSpecialClick?      () => void  — "특수" 키. 생략 시 비활성.
 *      className, style     — 컨테이너 속성 패스스루
 *
 *  · window.FullSecureKeypad 로 글로벌 등록 (React.forwardRef).
 * ========================================================================== */

const {
  useState: __fskUseState,
  useRef: __fskUseRef,
  useImperativeHandle: __fskUseImperativeHandle,
  useCallback: __fskUseCallback,
} = React;

/* ── 알파벳 ↔ 한글 듀얼 라벨 매핑 (두벌식 표준) ─────────────────────── */
const _FSK_HANGUL_MAP = {
  q: "ㅂ", w: "ㅈ", e: "ㄷ", r: "ㄱ", t: "ㅅ",
  y: "ㅛ", u: "ㅕ", i: "ㅑ", o: "ㅐ", p: "ㅔ",
  a: "ㅁ", s: "ㄴ", d: "ㅇ", f: "ㄹ", g: "ㅎ",
  h: "ㅗ", j: "ㅓ", k: "ㅏ", l: "ㅣ",
  z: "ㅋ", x: "ㅌ", c: "ㅊ", v: "ㅍ", b: "ㅠ",
  n: "ㅜ", m: "ㅡ",
};

/* ── 기본 키 배열 ──────────────────────────────────────────────────────
 * 각 행은 항상 10칸. 알파벳이 10칸을 못 채우면 뒷자리에 __slot 을 둬요.
 * __slot 은 ref.reorderEmptyCells() 로 셔플 가능한 "빈 자리 후보".
 * ─────────────────────────────────────────────────────────────────── */
const _FSK_NUMBER_ROW = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
const _FSK_QWERTY_ROW_1 = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]; // 10
const _FSK_QWERTY_ROW_2 = ["a", "s", "d", "f", "g", "h", "j", "k", "l"];       // 9
const _FSK_QWERTY_ROW_3 = ["z", "x", "c", "v", "b", "n", "m"];                 // 7

/** 공 셀 랜덤 배치: cells 개의 후보 슬롯에 nEmpty 개를 true 로 마크 */
function _fskRandomEmptyMask(slots, nEmpty) {
  const idx = [];
  for (let i = 0; i < slots; i += 1) idx.push(i);
  // Fisher-Yates
  for (let i = idx.length - 1; i > 0; i -= 1) {
    const j = Math.floor(Math.random() * (i + 1));
    const tmp = idx[i]; idx[i] = idx[j]; idx[j] = tmp;
  }
  const emptySet = new Set(idx.slice(0, Math.min(nEmpty, slots)));
  const mask = [];
  for (let i = 0; i < slots; i += 1) mask.push(emptySet.has(i));
  return mask;
}

/* ── Backspace 아이콘 (TDS mono, 24×24, currentColor) ── */
function _FskBackspaceIcon() {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path
        d="M8.4 5.5h10.85c.97 0 1.75.78 1.75 1.75v9.5c0 .97-.78 1.75-1.75 1.75H8.4a1.75 1.75 0 0 1-1.39-.68L3 12l4.01-5.82A1.75 1.75 0 0 1 8.4 5.5Z"
        stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"
      />
      <path d="m11.3 9.6 4.9 4.9m0-4.9-4.9 4.9" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
    </svg>
  );
}

/* ── Shift 아이콘 ── */
function _FskShiftIcon({ active }) {
  return (
    <svg width="22" height="22" viewBox="0 0 24 24" fill={active ? "currentColor" : "none"} aria-hidden="true">
      <path
        d="M12 3.5 4 11.5h4V19h8v-7.5h4L12 3.5Z"
        stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"
      />
    </svg>
  );
}

const _FullSecureKeypadInner = (props, ref) => {
  const {
    onKeyClick,
    onBackspaceClick,
    onSpaceClick,
    onSubmit,
    onSpecialClick,
    submitDisabled = false,
    submitButtonText = "입력 완료",
    backspaceAriaLabel = "한 글자 지우기",
    spaceAriaLabel = "띄어쓰기",
    specialAriaLabel = "특수문자",
    className = "",
    style,
    ...rest
  } = props;

  // 콜백 누락 경고
  if (typeof onKeyClick !== "function" && window.console && console.warn) {
    console.warn("[FullSecureKeypad] `onKeyClick` 은 필수예요.");
  }
  if (typeof onBackspaceClick !== "function" && window.console && console.warn) {
    console.warn("[FullSecureKeypad] `onBackspaceClick` 은 필수예요.");
  }
  if (typeof onSpaceClick !== "function" && window.console && console.warn) {
    console.warn("[FullSecureKeypad] `onSpaceClick` 은 필수예요.");
  }
  if (typeof onSubmit !== "function" && window.console && console.warn) {
    console.warn("[FullSecureKeypad] `onSubmit` 은 필수예요.");
  }

  const rootRef = __fskUseRef(null);
  const [shift, setShift] = __fskUseState(false);

  // 각 행의 빈 셀 마스크를 state 로 보관 → reorderEmptyCells() 로 갱신
  const [masks, setMasks] = __fskUseState(() => ({
    // 첫 행(숫자)은 10칸 가득 — 빈 셀 없음. 그 외 빈 자리에만 마스크 의미.
    // row1: qwerty 10자 가득. 빈 셀은 뒤 추가 없음 → 0.
    // row2: 9자 + 1빈. 행 10칸 기준 뒤쪽 slots 1 개 → 항상 1.
    // row3: 7자 + shift(좌) + backspace(우) + 1빈 = 10. slot 1.
    // 보안 목적 셔플은 2행/3행 내 "어느 자리에 진짜 알파벳을 놓을지"를 재배치.
    row2Order: _fskShuffleIndices(10),
    row3Order: _fskShuffleIndices(10),
  }));

  function _fskShuffleIndices(n) {
    const a = [];
    for (let i = 0; i < n; i += 1) a.push(i);
    for (let i = a.length - 1; i > 0; i -= 1) {
      const j = Math.floor(Math.random() * (i + 1));
      const t = a[i]; a[i] = a[j]; a[j] = t;
    }
    return a;
  }

  const reorderEmptyCells = __fskUseCallback(() => {
    setMasks({
      row2Order: _fskShuffleIndices(10),
      row3Order: _fskShuffleIndices(10),
    });
  }, []);

  __fskUseImperativeHandle(ref, () => ({
    reorderEmptyCells,
    get element() { return rootRef.current; },
  }), [reorderEmptyCells]);

  const handleKey = (raw) => {
    if (typeof onKeyClick !== "function") return;
    // shift 활성 & 알파벳이면 대문자
    if (shift && /^[a-z]$/.test(raw)) {
      onKeyClick(raw.toUpperCase());
    } else {
      onKeyClick(raw);
    }
  };

  const rootCls = "tds-fskeypad" + (className ? " " + className : "");

  /** 행 렌더: 10칸 고정.
   *  items: { kind: 'letter', value } | { kind: 'empty' } — row2/row3 에 사용.
   *  order: 0~9 인덱스 배열. 진짜 아이템을 이 순서로 배치해요.
   */
  function renderLetterRow(rowKey, items, order) {
    // order 의 앞부분 items.length 개가 "진짜 키가 들어갈 자리"를 결정.
    const placed = new Array(10).fill(null);
    for (let i = 0; i < items.length; i += 1) {
      placed[order[i]] = items[i];
    }
    return placed.map((item, idx) => {
      if (item === null) {
        return (
          <div
            key={rowKey + "-e-" + idx}
            className="tds-fskeypad__cell tds-fskeypad__cell--empty"
            aria-hidden="true"
          />
        );
      }
      const lower = item;
      const display = shift ? lower.toUpperCase() : lower;
      const hangul = _FSK_HANGUL_MAP[lower] || "";
      return (
        <button
          key={rowKey + "-k-" + idx + "-" + lower}
          type="button"
          className="tds-fskeypad__cell tds-fskeypad__cell--letter"
          aria-label={display + (hangul ? (" / " + hangul) : "")}
          onClick={() => handleKey(lower)}
        >
          <span className="tds-fskeypad__letter-main">{display}</span>
          {hangul ? <span className="tds-fskeypad__letter-sub">{hangul}</span> : null}
        </button>
      );
    });
  }

  return (
    <div
      ref={rootRef}
      className={rootCls}
      style={style}
      role="group"
      aria-label="전체 보안 키패드"
      {...rest}
    >
      {/* 1) 숫자 행 — 10칸 */}
      <div className="tds-fskeypad__row">
        {_FSK_NUMBER_ROW.map((n) => (
          <button
            key={"num-" + n}
            type="button"
            className="tds-fskeypad__cell tds-fskeypad__cell--letter tds-fskeypad__cell--number"
            aria-label={n}
            onClick={() => {
              if (typeof onKeyClick === "function") onKeyClick(n);
            }}
          >
            <span className="tds-fskeypad__letter-main">{n}</span>
          </button>
        ))}
      </div>

      {/* 2) QWERTY 1행 — 10칸 가득 */}
      <div className="tds-fskeypad__row">
        {renderLetterRow(
          "r1",
          _FSK_QWERTY_ROW_1.map((c) => c),
          // 이미 10개 가득 — 순서 고정(셔플 의미 없음)
          [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        )}
      </div>

      {/* 3) QWERTY 2행 — 9 letters + 1 empty (순서 랜덤) + Backspace(우측 고정이 아니라 동일 행 10칸 뒤 Backspace 별도 버튼) */}
      <div className="tds-fskeypad__row">
        {renderLetterRow("r2", _FSK_QWERTY_ROW_2, masks.row2Order)}
      </div>

      {/* 4) QWERTY 3행 — [Shift](1) + 7 letters + 1 empty + [Backspace](1) = 10 */}
      <div className="tds-fskeypad__row">
        <button
          type="button"
          className={
            "tds-fskeypad__cell tds-fskeypad__cell--action tds-fskeypad__cell--shift" +
            (shift ? " tds-fskeypad__cell--shift-on" : "")
          }
          aria-label={"영문 대소문자 전환" + (shift ? " (대문자 켜짐)" : " (소문자 켜짐)")}
          aria-pressed={shift ? "true" : "false"}
          onClick={() => setShift((s) => !s)}
        >
          <_FskShiftIcon active={shift} />
        </button>

        {/* 중앙 8칸 — 7 letters + 1 random empty (letters order) */}
        {renderLetterRow(
          "r3",
          _FSK_QWERTY_ROW_3,
          // 8칸 중 랜덤 배치 → order 의 0..7 범위만 사용하도록 slice
          masks.row3Order.slice(0, 8)
        )}

        <button
          type="button"
          className="tds-fskeypad__cell tds-fskeypad__cell--action tds-fskeypad__cell--backspace"
          aria-label={backspaceAriaLabel}
          onClick={() => {
            if (typeof onBackspaceClick === "function") onBackspaceClick();
          }}
        >
          <_FskBackspaceIcon />
        </button>
      </div>

      {/* 5) 하단 액션 행 — 특수 / Space / 입력 완료 */}
      <div className="tds-fskeypad__row tds-fskeypad__row--action">
        <button
          type="button"
          className="tds-fskeypad__action tds-fskeypad__action--special"
          aria-label={specialAriaLabel}
          disabled={typeof onSpecialClick !== "function"}
          onClick={() => {
            if (typeof onSpecialClick === "function") onSpecialClick();
          }}
        >
          <span className="tds-fskeypad__action-label">특수</span>
        </button>

        <button
          type="button"
          className="tds-fskeypad__action tds-fskeypad__action--space"
          aria-label={spaceAriaLabel}
          onClick={() => {
            if (typeof onSpaceClick === "function") onSpaceClick();
          }}
        >
          <span className="tds-fskeypad__action-label">Space</span>
        </button>

        <button
          type="button"
          className="tds-fskeypad__action tds-fskeypad__action--submit"
          aria-label={submitButtonText}
          disabled={submitDisabled}
          onClick={() => {
            if (submitDisabled) return;
            if (typeof onSubmit === "function") onSubmit();
          }}
        >
          <span className="tds-fskeypad__action-label">{submitButtonText}</span>
        </button>
      </div>
    </div>
  );
};

const FullSecureKeypad = React.forwardRef(_FullSecureKeypadInner);

// 글로벌 등록
window.FullSecureKeypad = FullSecureKeypad;
