/* ============================================================================
 * 서명전에 — TDS SegmentedControl 컴포넌트
 *  · 여러 선택지 중 하나를 선택하는 라디오 형식의 UI 요소.
 *  · 2 서브:
 *      SegmentedControl       — 컨테이너 (radiogroup)
 *      SegmentedControl.Item  — 각 선택지 (radio)
 *
 *  · controlled / uncontrolled 모두 지원:
 *      controlled   — value + onChange(v)
 *      uncontrolled — defaultValue + 내부 useState
 *
 *  · alignment:
 *      fixed (기본) — 모든 아이템이 동일한 너비 (flex: 1 1 0)
 *      fluid       — 아이템 너비 = 글자 수, 컨테이너를 넘으면 가로 스크롤.
 *                    스크롤로 첫 아이템이 가려지면 좌측 화살표 버튼 등장,
 *                    클릭 시 부드럽게 처음으로 스크롤.
 *
 *  · size: small (기본, 32px / sub-ty-7) / large (40px / sub-ty-5)
 *      Item 의 size prop 으로 개별 오버라이드 가능.
 *
 *  · 접근성:
 *      · 컨테이너 role="radiogroup" + aria-orientation="horizontal"
 *      · 각 Item role="radio" + tabIndex=0 + aria-checked (자동)
 *      · Item 내부 라벨은 <span id="…-label"> 로 분리되고
 *        radio 가 aria-labelledby 로 자동 연결됨
 *      · 키보드: ← → ↑ ↓ 로 이전/다음 이동, Home/End 양 끝, Space/Enter 활성
 *      · 좌측 화살표 버튼 aria-label="처음으로 이동", 보이지 않을 때 tabIndex=-1
 * ========================================================================== */

const __SEGMENTED_SIZES  = { small: 1, large: 1 };
const __SEGMENTED_ALIGNS = { fixed: 1, fluid: 1 };

let __segmentedIdCounter = 0;
function __segmentedNextId() {
  __segmentedIdCounter += 1;
  return "tds-seg-" + __segmentedIdCounter;
}

// 컨테이너 → Item 으로 상태/사이즈/이벤트 핸들러를 전달하기 위한 컨텍스트.
const __SegmentedControlContext = React.createContext({
  currentValue: undefined,
  onSelect: function () {},
  size: "small",
  onItemKeyDown: function () {},
});

// ----- 좌측 화살표 SVG (14px chevron-left) -----
function __SegmentedLeftArrowSvg() {
  return (
    <svg
      className="tds-segmented__left-arrow-svg"
      viewBox="0 0 14 14"
      aria-hidden="true"
      focusable="false"
    >
      <polyline points="9,2 4,7 9,12" />
    </svg>
  );
}

function SegmentedControl({
  children,
  value,
  defaultValue,
  onChange,
  size = "small",
  alignment = "fixed",
  className = "",
  style,
  id,
  "aria-label": ariaLabel,
  "aria-labelledby": ariaLabelledBy,
  ...rest
}) {
  // ----- props 검증 -----
  if (!__SEGMENTED_SIZES[size]) {
    if (window.console && console.warn) {
      console.warn(
        `[SegmentedControl] size 는 "small" | "large" 만 가능해요. 받은 값: ${size}`
      );
    }
  }
  if (!__SEGMENTED_ALIGNS[alignment]) {
    if (window.console && console.warn) {
      console.warn(
        `[SegmentedControl] alignment 는 "fixed" | "fluid" 만 가능해요. 받은 값: ${alignment}`
      );
    }
  }
  const safeSize  = __SEGMENTED_SIZES[size]      ? size      : "small";
  const safeAlign = __SEGMENTED_ALIGNS[alignment] ? alignment : "fixed";

  // ----- controlled vs uncontrolled -----
  const isControlled = value !== undefined;
  const [internal, setInternal] = React.useState(
    typeof defaultValue === "string" ? defaultValue : undefined
  );
  const currentValue = isControlled ? value : internal;

  // controlled 인데 onChange 가 없으면 read-only 와 다름없음 — 한 번 경고
  if (isControlled && typeof onChange !== "function") {
    if (window.console && console.warn) {
      console.warn(
        "[SegmentedControl] value 만 주고 onChange 는 안 줬어요. " +
        "controlled 모드에서는 onChange 로 외부 상태를 갱신해야 해요."
      );
    }
  }

  // ----- 자식 → values 배열 (키보드 이동 / 선택 시 인덱스 계산) -----
  const childArray = React.Children.toArray(children).filter(function (c) {
    return React.isValidElement(c);
  });
  const itemValues = childArray.map(function (c) {
    return c.props && c.props.value;
  });

  // ----- 선택 핸들러 -----
  const handleSelect = function (v) {
    if (!isControlled) setInternal(v);
    if (typeof onChange === "function") onChange(v);
  };

  // ----- fluid 스크롤 — 첫 아이템 가림 여부 추적 → 좌측 화살표 표시 -----
  const trackRef = React.useRef(null);
  const [showLeftArrow, setShowLeftArrow] = React.useState(false);

  React.useEffect(function () {
    // fixed 면 화살표 항상 숨김
    if (safeAlign !== "fluid") {
      setShowLeftArrow(false);
      return;
    }
    const el = trackRef.current;
    if (!el) return;

    const update = function () {
      // 첫 아이템이 가려진 정도 — scrollLeft > 8px 이면 화살표 표시
      setShowLeftArrow(el.scrollLeft > 8);
    };
    el.addEventListener("scroll", update, { passive: true });

    // 초기 상태 + 리사이즈 시 재계산
    update();
    let ro = null;
    if (typeof ResizeObserver !== "undefined") {
      ro = new ResizeObserver(update);
      ro.observe(el);
    }
    return function () {
      el.removeEventListener("scroll", update);
      if (ro) ro.disconnect();
    };
  }, [safeAlign]);

  const handleLeftArrowClick = function () {
    const el = trackRef.current;
    if (!el) return;
    if (typeof el.scrollTo === "function") {
      el.scrollTo({ left: 0, behavior: "smooth" });
    } else {
      el.scrollLeft = 0;
    }
  };

  // ----- 키보드 이동 핸들러 (Item 에서 호출) -----
  const handleItemKeyDown = function (e, fromValue) {
    const k = e.key;
    if (
      k !== "ArrowLeft" && k !== "ArrowRight" &&
      k !== "ArrowUp"   && k !== "ArrowDown"  &&
      k !== "Home"      && k !== "End"        &&
      k !== " "         && k !== "Enter"
    ) return;

    const idx = itemValues.indexOf(fromValue);
    if (idx < 0) return;

    // Space / Enter — 현재 항목 활성화
    if (k === " " || k === "Enter") {
      e.preventDefault();
      handleSelect(fromValue);
      return;
    }

    // 이동 — 다음 인덱스 계산 (양 끝 wrap-around)
    let nextIdx = idx;
    if (k === "ArrowLeft" || k === "ArrowUp") {
      nextIdx = idx === 0 ? itemValues.length - 1 : idx - 1;
    } else if (k === "ArrowRight" || k === "ArrowDown") {
      nextIdx = idx === itemValues.length - 1 ? 0 : idx + 1;
    } else if (k === "Home") {
      nextIdx = 0;
    } else if (k === "End") {
      nextIdx = itemValues.length - 1;
    }
    e.preventDefault();
    const nextVal = itemValues[nextIdx];
    handleSelect(nextVal);

    // 포커스도 새 항목으로 이동 — radiogroup 키보드 패턴
    const trackEl = trackRef.current;
    if (trackEl) {
      const items = trackEl.querySelectorAll('[role="radio"]');
      if (items[nextIdx] && typeof items[nextIdx].focus === "function") {
        items[nextIdx].focus();
        // fluid 모드에서 화면 밖이면 살짝 스크롤
        if (safeAlign === "fluid" && typeof items[nextIdx].scrollIntoView === "function") {
          items[nextIdx].scrollIntoView({
            behavior: "smooth",
            block: "nearest",
            inline: "nearest",
          });
        }
      }
    }
  };

  // ----- 컨텍스트 value -----
  const ctx = {
    currentValue: currentValue,
    onSelect: handleSelect,
    size: safeSize,
    onItemKeyDown: handleItemKeyDown,
  };

  // ----- 클래스 조립 -----
  const wrapCls = [
    "tds-segmented",
    `tds-segmented--size-${safeSize}`,
    `tds-segmented--align-${safeAlign}`,
    className,
  ]
    .filter(Boolean)
    .join(" ");

  return (
    <div id={id} className={wrapCls} style={style} {...rest}>
      <div
        ref={trackRef}
        className="tds-segmented__track"
        role="radiogroup"
        aria-orientation="horizontal"
        aria-label={ariaLabel}
        aria-labelledby={ariaLabelledBy}
      >
        <__SegmentedControlContext.Provider value={ctx}>
          {children}
        </__SegmentedControlContext.Provider>
      </div>
      {safeAlign === "fluid" ? (
        <button
          type="button"
          className={
            "tds-segmented__left-arrow" +
            (showLeftArrow ? " tds-segmented__left-arrow--visible" : "")
          }
          onClick={handleLeftArrowClick}
          aria-label="처음으로 이동"
          aria-hidden={!showLeftArrow}
          tabIndex={showLeftArrow ? 0 : -1}
        >
          <__SegmentedLeftArrowSvg />
        </button>
      ) : null}
    </div>
  );
}

// =============================================================================
// SegmentedControl.Item
//   · 각각의 선택지 — role="radio" + aria-checked 자동.
//   · onClick 시 부모 컨텍스트의 onSelect(value) 호출.
//   · 라벨은 <span id="…-label"> 로 분리하고 radio 가 aria-labelledby 로 연결.
// =============================================================================
function SegmentedControlItem({
  children,
  value,
  size: sizeOverride,
  className = "",
  style,
  id,
  ...rest
}) {
  const ctx = React.useContext(__SegmentedControlContext);

  // Item 의 size 가 small/large 가 아닌 값을 받으면 경고
  if (sizeOverride !== undefined && !__SEGMENTED_SIZES[sizeOverride]) {
    if (window.console && console.warn) {
      console.warn(
        `[SegmentedControl.Item] size 는 "small" | "large" 만 가능해요. 받은 값: ${sizeOverride}`
      );
    }
  }
  const itemSize =
    sizeOverride && __SEGMENTED_SIZES[sizeOverride] ? sizeOverride : ctx.size;

  // value 누락 방지
  if (value === undefined || value === null || value === "") {
    if (window.console && console.warn) {
      console.warn(
        "[SegmentedControl.Item] value 는 필수예요. (onChange 콜백 인자로 전달돼요)"
      );
    }
  }

  // 라벨용 stable id — 한 번만 생성
  const labelIdRef = React.useRef(null);
  if (labelIdRef.current == null) {
    const baseId =
      id || ("tds-seg-item-" + Math.random().toString(36).slice(2, 9));
    labelIdRef.current = baseId + "-label";
  }

  const isSelected =
    ctx.currentValue !== undefined && ctx.currentValue === value;

  const cls = [
    "tds-segmented__item",
    `tds-segmented__item--size-${itemSize}`,
    isSelected ? "tds-segmented__item--selected" : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  const handleClick = function () {
    if (typeof ctx.onSelect === "function") ctx.onSelect(value);
  };

  const handleKeyDown = function (e) {
    if (typeof ctx.onItemKeyDown === "function") ctx.onItemKeyDown(e, value);
  };

  return (
    <button
      id={id}
      type="button"
      role="radio"
      tabIndex={0}
      aria-checked={isSelected}
      aria-labelledby={labelIdRef.current}
      className={cls}
      style={style}
      onClick={handleClick}
      onKeyDown={handleKeyDown}
      {...rest}
    >
      <span id={labelIdRef.current} className="tds-segmented__item-label">
        {children}
      </span>
    </button>
  );
}

SegmentedControl.Item = SegmentedControlItem;

window.SegmentedControl = SegmentedControl;
window.SegmentedControlItem = SegmentedControlItem;
Object.assign(window, { SegmentedControl, SegmentedControlItem });
