/* ============================================================================
 * 서명전에 — TDS Rating 컴포넌트
 *  · 사용자가 항목/콘텐츠에 대한 평가를 제공하거나(interactive) 결과를
 *    읽기 전용으로 표시(readOnly)하는 별점 UI.
 *
 *  · 두 모드:
 *      readOnly=false → max 개의 별 버튼, 클릭 시 onValueChange
 *      readOnly=true  → 평가 결과 표시. variant 로 형태 변경 가능
 *
 *  · size:
 *      readOnly=false → "medium" | "large" | "big"                (3종)
 *      readOnly=true  → "tiny" | "small" | "medium" | "large" | "big"  (5종)
 *
 *  · variant (readOnly=true 전용):
 *      "full"     — max 개의 별 + 숫자 값
 *      "compact"  — 별 1개 + 숫자 값
 *      "iconOnly" — max 개의 별만 (숫자 없음)
 *
 *  · RatingProps:
 *      readOnly *      boolean  (필수)
 *      value *         number   (0 ~ max, 자동 클램프)
 *      size *          위 size 테이블
 *      variant *       위 variant 테이블 (readOnly=true 일 때만)
 *      max             number   (기본 5)
 *      onValueChange   (v:number)=>void   (readOnly=false 일 때만 호출)
 *      disabled        boolean  (readOnly=false 일 때만)
 *      aria-label      기본 "별점 평가"
 *      aria-valuetext  기본 "max점 만점 중 value점"
 *
 *  · 접근성:
 *      · interactive 모드: 시각적으로 숨긴 <input type="range"> 포함
 *        → 키보드 ← → 로 값 변경, 스크린 리더는 슬라이더 의미 읽음
 *      · 별 SVG 는 aria-hidden="true" — 값은 aria-valuetext 로 전달
 *      · 루트에 role + aria-label + aria-valuetext 부착
 * ========================================================================== */

const __RATING_INTERACTIVE_SIZES = { medium: 1, large: 1, big: 1 };
const __RATING_READONLY_SIZES    = { tiny: 1, small: 1, medium: 1, large: 1, big: 1 };
const __RATING_VARIANTS          = { full: 1, compact: 1, iconOnly: 1 };

// ----- 별 SVG (5각성, currentColor 로 색 제어) -----
function __RatingStarSvg() {
  return (
    <svg
      className="tds-rating__star-svg"
      viewBox="0 0 24 24"
      aria-hidden="true"
      focusable="false"
    >
      <path d="M12 2.5l2.93 6.22 6.82.82-5.03 4.7 1.32 6.86L12 17.77 5.96 21.1l1.32-6.86-5.03-4.7 6.82-.82L12 2.5z" />
    </svg>
  );
}

function Rating({
  readOnly,
  value,
  size,
  variant,
  max = 5,
  onValueChange,
  disabled = false,
  className = "",
  style,
  id,
  "aria-label": ariaLabel,
  "aria-valuetext": ariaValuetext,
  ...rest
}) {
  // readOnly 필수
  if (typeof readOnly !== "boolean") {
    if (window.console && console.warn) {
      console.warn(
        `[Rating] \`readOnly\` 는 필수 boolean prop 이에요. 받은 값: ${readOnly}`
      );
    }
  }
  const isReadOnly = readOnly === true;

  // size 검증 — readOnly 여부에 따라 허용 값이 달라짐
  const sizeMap = isReadOnly
    ? __RATING_READONLY_SIZES
    : __RATING_INTERACTIVE_SIZES;
  if (!sizeMap[size]) {
    if (window.console && console.warn) {
      const allowed = isReadOnly
        ? '"tiny" | "small" | "medium" | "large" | "big"'
        : '"medium" | "large" | "big"';
      console.warn(
        `[Rating] readOnly=${isReadOnly} 일 때 \`size\` 는 ${allowed} 중 하나여야 해요. 받은 값: ${size}`
      );
    }
  }
  const safeSize = sizeMap[size] ? size : "medium";

  // variant 검증 — readOnly=true 일 때만 의미
  if (!isReadOnly && variant != null) {
    if (window.console && console.warn) {
      console.warn(
        "[Rating] `variant` 는 `readOnly=true` 일 때만 사용할 수 있어요. 무시돼요."
      );
    }
  }
  if (isReadOnly && variant != null && !__RATING_VARIANTS[variant]) {
    if (window.console && console.warn) {
      console.warn(
        `[Rating] \`variant\` 는 "full" | "compact" | "iconOnly" 중 하나여야 해요. 받은 값: ${variant}`
      );
    }
  }
  const safeVariant = isReadOnly
    ? (__RATING_VARIANTS[variant] ? variant : "full")
    : null;

  // disabled / onValueChange — readOnly=true 일 때 경고
  if (isReadOnly && disabled) {
    if (window.console && console.warn) {
      console.warn(
        "[Rating] `disabled` 는 `readOnly=true` 일 때 사용할 수 없어요. 무시돼요."
      );
    }
  }
  if (isReadOnly && typeof onValueChange === "function") {
    if (window.console && console.warn) {
      console.warn(
        "[Rating] `onValueChange` 는 `readOnly=true` 일 때 호출되지 않아요."
      );
    }
  }
  const safeDisabled = !isReadOnly && disabled === true;

  // max 정규화 — 1 이상 정수
  const safeMax =
    typeof max === "number" && Number.isFinite(max) && max >= 1
      ? Math.max(1, Math.round(max))
      : 5;

  // value 정규화 — [0, safeMax] 클램프 + 정수
  const rawValue =
    typeof value === "number" && Number.isFinite(value) ? value : 0;
  const safeValueInt = Math.max(
    0,
    Math.min(safeMax, Math.round(rawValue))
  );

  const finalAriaLabel = ariaLabel != null ? ariaLabel : "별점 평가";
  const finalValuetext =
    ariaValuetext != null
      ? ariaValuetext
      : `${safeMax}점 만점 중 ${safeValueInt}점`;

  const cls = [
    "tds-rating",
    `tds-rating--size-${safeSize}`,
    isReadOnly ? "tds-rating--readonly" : "tds-rating--interactive",
    safeVariant ? `tds-rating--variant-${safeVariant}` : "",
    safeDisabled ? "is-disabled" : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  // -----------------------------
  // Interactive 모드
  // -----------------------------
  if (!isReadOnly) {
    const handleClick = function (next) {
      if (safeDisabled) return;
      if (typeof onValueChange === "function") onValueChange(next);
    };
    const handleSliderChange = function (e) {
      if (safeDisabled) return;
      const next = Math.max(
        0,
        Math.min(safeMax, Math.round(Number(e.target.value) || 0))
      );
      if (typeof onValueChange === "function") onValueChange(next);
    };

    const stars = [];
    for (let i = 0; i < safeMax; i++) {
      const filled = i < safeValueInt;
      stars.push(
        <button
          key={i}
          type="button"
          className={`tds-rating__star${filled ? " is-filled" : ""}`}
          onClick={() => handleClick(i + 1)}
          disabled={safeDisabled}
          aria-hidden="true"
          tabIndex={-1}
        >
          <__RatingStarSvg />
        </button>
      );
    }

    return (
      <span
        id={id}
        className={cls}
        style={style}
        role="group"
        aria-label={finalAriaLabel}
        aria-valuetext={finalValuetext}
        aria-disabled={safeDisabled || undefined}
        {...rest}
      >
        {stars}
        <input
          type="range"
          className="tds-rating__sr-input"
          min={0}
          max={safeMax}
          step={1}
          value={safeValueInt}
          onChange={handleSliderChange}
          disabled={safeDisabled}
          aria-label={finalAriaLabel}
          aria-valuetext={finalValuetext}
        />
      </span>
    );
  }

  // -----------------------------
  // ReadOnly — full / iconOnly
  // -----------------------------
  if (safeVariant === "full" || safeVariant === "iconOnly") {
    const stars = [];
    for (let i = 0; i < safeMax; i++) {
      const filled = i < safeValueInt;
      stars.push(
        <span
          key={i}
          className={`tds-rating__star${filled ? " is-filled" : ""}`}
          aria-hidden="true"
        >
          <__RatingStarSvg />
        </span>
      );
    }
    return (
      <span
        id={id}
        className={cls}
        style={style}
        role="img"
        aria-label={finalAriaLabel}
        aria-valuetext={finalValuetext}
        {...rest}
      >
        <span className="tds-rating__stars" aria-hidden="true">
          {stars}
        </span>
        {safeVariant === "full" ? (
          <span className="tds-rating__value" aria-hidden="true">
            {safeValueInt}
          </span>
        ) : null}
      </span>
    );
  }

  // -----------------------------
  // ReadOnly — compact (별 1개 + 값)
  // -----------------------------
  return (
    <span
      id={id}
      className={cls}
      style={style}
      role="img"
      aria-label={finalAriaLabel}
      aria-valuetext={finalValuetext}
      {...rest}
    >
      <span className="tds-rating__star is-filled" aria-hidden="true">
        <__RatingStarSvg />
      </span>
      <span className="tds-rating__value" aria-hidden="true">
        {safeValueInt}
      </span>
    </span>
  );
}

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