/* ============================================================================
 * 서명전에 — TDS Stepper 컴포넌트
 *  · 여러 단계를 시각적으로 보여주는 단계 리스트.
 *  · ProgressStepper(#142) 와 역할 구분:
 *      ProgressStepper — "1/3, 2/3, 3/3" 처럼 진행 위치 강조.
 *      Stepper        — 절차 안내·체크리스트·가이드 카드 형태로 단계별
 *                       제목·설명·우측 액션을 함께 보여 주기.
 *
 *  · 2 컨테이너 + 5 서브:
 *      Stepper                 — 루트, children(StepperRow…) stagger 등장 모션
 *      StepperRow              — 한 행, left / center / right 슬롯 + hideLine
 *      StepperRow.Texts        — center 슬롯 텍스트 (type A/B/C 제목·설명)
 *      StepperRow.NumberIcon   — left 숫자 아이콘 (1~9)
 *      StepperRow.AssetFrame   — left 에셋 프레임 (이미지/이모지)
 *      StepperRow.RightArrow   — right 화살표 (>)
 *      StepperRow.RightButton  — right 버튼 (TDS Button 위임)
 *
 *  · Stepper props:
 *      play         (boolean, 기본 true) — 등장 애니메이션 재생 여부.
 *                   false 면 모션 없이 그대로 렌더.
 *      delay        (number, 기본 0)     — 첫 행이 등장하기 전 지연 (초).
 *      staggerDelay (number, 기본 0.1)  — 행 간격 (초).
 *
 *  · 등장 모션:
 *      각 StepperRow 에 CSS keyframe `tds-stepper-row-in`
 *      (translateY(8px) → 0, opacity 0 → 1, 360ms cubic-bezier(0.22,1,0.36,1) both).
 *      Stepper 가 React.cloneElement 로 자식 row 에 인덱스 + delay 변수
 *      (--tds-stepper-row-delay) 를 inline style 로 주입.
 *      play=false 면 inline style 로 animation: none + opacity 1 강제.
 *
 *  · 연결선(hideLine=false 기본):
 *      좌측 NumberIcon / AssetFrame 컬럼의 가운데에서 시작해 row bottom 까지
 *      grey-200 1px 세로선이 떨어져요. 마지막 행은 hideLine=true 로 끔.
 *
 *  · 접근성:
 *      Stepper 루트 role="list" + aria-label="진행 단계" (기본).
 *      StepperRow role="listitem".
 *      장식적 SVG 는 모두 aria-hidden="true".
 * ========================================================================== */

const __STEPPER_TEXT_TYPES = { A: 1, B: 1, C: 1 };

// 에셋 프레임 모양 — Asset.frameShape preset 의 우리 측 매핑
const __STEPPER_FRAME_SHAPES = {
  CircleSmall:  { size: 24, radius: "50%" },
  CircleMedium: { size: 36, radius: "50%" },
  CircleLarge:  { size: 48, radius: "50%" },
  CleanW24:     { size: 24, radius: 0 },
  CleanW32:     { size: 32, radius: 0 },
  RectSmall:    { size: 24, radius: 6 },
  RectMedium:   { size: 36, radius: 8 },
  RectLarge:    { size: 48, radius: 10 },
};

// =============================================================================
// Stepper — 컨테이너 (children 에 stagger 등장 모션 주입)
// =============================================================================
function Stepper({
  children,
  play = true,
  delay = 0,
  staggerDelay = 0.1,
  className = "",
  style,
  id,
  "aria-label": ariaLabel,
  ...rest
}) {
  // ----- props 검증 -----
  const safePlay = play !== false; // truthy 만 true 로 (단, false 명시는 false)
  const safeDelay = typeof delay === "number" && isFinite(delay) ? Math.max(0, delay) : 0;
  const safeStagger = typeof staggerDelay === "number" && isFinite(staggerDelay)
    ? Math.max(0, staggerDelay)
    : 0.1;

  // ----- 자식 → 인덱스 + delay 주입 -----
  const childArray = React.Children.toArray(children).filter(function (c) {
    return React.isValidElement(c);
  });
  const total = childArray.length;

  const enhanced = childArray.map(function (child, idx) {
    const rowDelay = safeDelay + idx * safeStagger;
    // 자식이 이미 받은 style 을 보존하면서 inline 변수 / animation 합성
    const childStyle = (child.props && child.props.style) || {};
    const animStyle = safePlay
      ? {
          ...childStyle,
          animation: `tds-stepper-row-in 360ms cubic-bezier(0.22,1,0.36,1) both`,
          animationDelay: `${rowDelay}s`,
        }
      : {
          ...childStyle,
          animation: "none",
          opacity: 1,
          transform: "none",
        };
    // hideLine 이 명시되지 않은 마지막 자식은 자동으로 hideLine=true
    const childProps = child.props || {};
    const autoHideLine = idx === total - 1 ? true : !!childProps.hideLine;
    return React.cloneElement(child, {
      style: animStyle,
      hideLine: childProps.hideLine !== undefined ? childProps.hideLine : autoHideLine,
      __tdsStepperIsLast: idx === total - 1,
    });
  });

  const cls = ["tds-stepper", className].filter(Boolean).join(" ");
  return (
    <div
      id={id}
      className={cls}
      style={style}
      role="list"
      aria-label={ariaLabel != null ? ariaLabel : "진행 단계"}
      {...rest}
    >
      {enhanced}
    </div>
  );
}

// =============================================================================
// StepperRow — 한 행 (left + center + right + 연결선)
// =============================================================================
function StepperRow({
  left,
  center,
  right,
  hideLine = false,
  className = "",
  style,
  id,
  __tdsStepperIsLast, // Stepper 가 주입 — 외부 노출하지 않음
  ...rest
}) {
  // 사용자 친화 경고
  if (left == null && window.console && console.warn) {
    console.warn("[StepperRow] left prop 이 비어있어요. 보통 NumberIcon 또는 AssetFrame 을 넣어요.");
  }
  if (center == null && window.console && console.warn) {
    console.warn("[StepperRow] center prop 이 비어있어요. 보통 StepperRow.Texts 를 넣어요.");
  }

  const cls = [
    "tds-stepper-row",
    hideLine ? "tds-stepper-row--no-line" : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  // 외부에 새는 건 안 좋으니 __tdsStepperIsLast 는 비표준 prop 으로 DOM 에 안 흘러가게
  void __tdsStepperIsLast;

  return (
    <div id={id} className={cls} style={style} role="listitem" {...rest}>
      <div className="tds-stepper-row__left">
        {left}
        {hideLine ? null : <span className="tds-stepper-row__line" aria-hidden="true" />}
      </div>
      <div className="tds-stepper-row__center">{center}</div>
      {right ? <div className="tds-stepper-row__right">{right}</div> : null}
    </div>
  );
}

// =============================================================================
// StepperRow.Texts — type A/B/C 제목 + 설명
// =============================================================================
function StepperRowTexts({
  type,
  title,
  description,
  titleProps,
  descriptionProps,
  className = "",
  style,
  ...rest
}) {
  if (!__STEPPER_TEXT_TYPES[type]) {
    if (window.console && console.warn) {
      console.warn(`[StepperRow.Texts] type 은 "A" | "B" | "C" 만 가능해요. 받은 값: ${type}. 'A' 사용.`);
    }
  }
  const safeType = __STEPPER_TEXT_TYPES[type] ? type : "A";
  // 사이즈 매핑
  //   A: title ty-5 / desc ty-6
  //   B: title ty-4 / desc ty-6
  //   C: title ty-5 / desc ty-7
  const titleClass =
    safeType === "B"
      ? "ty-4 w-bold tds-stepper-text__title"
      : "ty-5 w-bold tds-stepper-text__title";
  const descClass =
    safeType === "C"
      ? "ty-7 tds-stepper-text__desc"
      : "ty-6 tds-stepper-text__desc";

  const tProps = titleProps || {};
  const dProps = descriptionProps || {};

  const cls = ["tds-stepper-text", className].filter(Boolean).join(" ");

  return (
    <div className={cls} style={style} {...rest}>
      <div
        {...tProps}
        className={[titleClass, tProps.className].filter(Boolean).join(" ")}
        style={tProps.style}
      >
        {title}
      </div>
      {description != null && description !== "" ? (
        <div
          {...dProps}
          className={[descClass, dProps.className].filter(Boolean).join(" ")}
          style={dProps.style}
        >
          {description}
        </div>
      ) : null}
    </div>
  );
}

// =============================================================================
// StepperRow.NumberIcon — 1~9 숫자 아이콘 (28px 흰 원 + 파란 ring + 파란 숫자)
// =============================================================================
function StepperRowNumberIcon({
  number,
  color,
  bgColor,
  className = "",
  style,
  ...rest
}) {
  const validNum = typeof number === "number" && number >= 1 && number <= 9 && Math.floor(number) === number;
  if (!validNum && window.console && console.warn) {
    console.warn(`[StepperRow.NumberIcon] number 는 1~9 정수만 가능해요. 받은 값: ${number}.`);
  }
  const safeNum = validNum ? number : 1;

  const inlineStyle = { ...(style || {}) };
  if (color) inlineStyle["--tds-stepper-number-color"] = color;
  if (bgColor) inlineStyle["--tds-stepper-number-bg"] = bgColor;

  const cls = ["tds-stepper-number-icon", className].filter(Boolean).join(" ");

  return (
    <div
      className={cls}
      style={inlineStyle}
      role="img"
      aria-label={`${safeNum}단계`}
      {...rest}
    >
      <span aria-hidden="true">{safeNum}</span>
    </div>
  );
}

// =============================================================================
// StepperRow.AssetFrame — Asset.Frame 의 우리 측 시뮬레이션 (이미지/이모지 컨테이너)
// =============================================================================
function StepperRowAssetFrame({
  shape,
  content,
  backgroundColor,
  className = "",
  style,
  ...rest
}) {
  const sp = (typeof shape === "string" && __STEPPER_FRAME_SHAPES[shape]) || null;
  if (!sp && window.console && console.warn) {
    console.warn(
      `[StepperRow.AssetFrame] shape 은 "CircleSmall|CircleMedium|CircleLarge|CleanW24|CleanW32|RectSmall|RectMedium|RectLarge" 중 하나여야 해요. 받은 값: ${shape}. CircleMedium 사용.`
    );
  }
  const final = sp || __STEPPER_FRAME_SHAPES.CircleMedium;

  const inlineStyle = {
    width: `${final.size}px`,
    height: `${final.size}px`,
    borderRadius: typeof final.radius === "number" ? `${final.radius}px` : final.radius,
    background:
      backgroundColor && backgroundColor !== "transparent"
        ? backgroundColor
        : "transparent",
    ...(style || {}),
  };

  const cls = ["tds-stepper-asset-frame", className].filter(Boolean).join(" ");

  return (
    <div className={cls} style={inlineStyle} aria-hidden="true" {...rest}>
      {content}
    </div>
  );
}

// =============================================================================
// StepperRow.RightArrow — chevron-right 아이콘 (24px)
// =============================================================================
function StepperRowRightArrow({
  color,
  className = "",
  style,
  "aria-label": ariaLabel,
  ...rest
}) {
  const inlineStyle = { ...(style || {}) };
  if (color) inlineStyle["--tds-stepper-arrow-color"] = color;
  const cls = ["tds-stepper-right-arrow", className].filter(Boolean).join(" ");
  return (
    <span
      className={cls}
      style={inlineStyle}
      role={ariaLabel ? "img" : undefined}
      aria-label={ariaLabel}
      aria-hidden={ariaLabel ? undefined : true}
      {...rest}
    >
      <svg
        viewBox="0 0 24 24"
        width="20"
        height="20"
        fill="none"
        focusable="false"
      >
        <polyline
          points="9,5 16,12 9,19"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        />
      </svg>
    </span>
  );
}

// =============================================================================
// StepperRow.RightButton — TDS Button 위임 (없으면 native button 폴백)
// =============================================================================
function StepperRowRightButton({
  children,
  size = "small",
  color = "primary",
  className = "",
  style,
  ...rest
}) {
  // window.Button 이 로드돼 있으면 위임
  if (typeof window !== "undefined" && typeof window.Button === "function") {
    const TdsButton = window.Button;
    return (
      <TdsButton
        size={size}
        color={color}
        variant="fill"
        display="inline"
        className={["tds-stepper-right-button", className].filter(Boolean).join(" ")}
        style={style}
        {...rest}
      >
        {children}
      </TdsButton>
    );
  }
  // 폴백 — TDS Button 미로드 시
  const cls = [
    "tds-stepper-right-button",
    "tds-stepper-right-button--fallback",
    `tds-stepper-right-button--size-${size}`,
    `tds-stepper-right-button--color-${color}`,
    className,
  ]
    .filter(Boolean)
    .join(" ");
  return (
    <button type="button" className={cls} style={style} {...rest}>
      {children}
    </button>
  );
}

// ----- 서브 매달기 -----
StepperRow.Texts       = StepperRowTexts;
StepperRow.NumberIcon  = StepperRowNumberIcon;
StepperRow.AssetFrame  = StepperRowAssetFrame;
StepperRow.RightArrow  = StepperRowRightArrow;
StepperRow.RightButton = StepperRowRightButton;

// 일부 스펙에서 Stepper.NumberIcon / Stepper.AssetFrame / Stepper.RightArrow 로
// 표기 — 동일 인스턴스를 양쪽에 매달아 두 표기 모두 동작
Stepper.Row          = StepperRow;
Stepper.NumberIcon   = StepperRowNumberIcon;
Stepper.AssetFrame   = StepperRowAssetFrame;
Stepper.RightArrow   = StepperRowRightArrow;
Stepper.RightButton  = StepperRowRightButton;
Stepper.Texts        = StepperRowTexts;

window.Stepper                   = Stepper;
window.StepperRow                = StepperRow;
window.StepperRowTexts           = StepperRowTexts;
window.StepperRowNumberIcon      = StepperRowNumberIcon;
window.StepperRowAssetFrame      = StepperRowAssetFrame;
window.StepperRowRightArrow      = StepperRowRightArrow;
window.StepperRowRightButton     = StepperRowRightButton;
Object.assign(window, {
  Stepper, StepperRow,
  StepperRowTexts, StepperRowNumberIcon,
  StepperRowAssetFrame, StepperRowRightArrow, StepperRowRightButton,
});
