/* ============================================================================
 * 서명전에 — TDS Paragraph 컴포넌트
 *  · 한 단락 안에 텍스트/아이콘/뱃지/링크를 자연스럽게 섞을 수 있어요.
 *  · 4 서브:
 *      Paragraph.Text   — 인라인 텍스트 (typography/fontWeight/color 부분 오버라이드)
 *      Paragraph.Icon   — 인라인 아이콘 (URL 또는 IOSIcon name, mono 마스크)
 *      Paragraph.Badge  — 인라인 뱃지 (style fill/weak × type blue/teal/green/red/yellow/elephant)
 *      Paragraph.Link   — 인라인 링크 (type underline/clear, as 다른 태그 가능)
 *
 *  · root props (ParagraphProps):
 *      typography *   "t1"~"t7" | "st1"~"st13"   필수
 *      display        "block" | "inline"          기본 "block"
 *      ellipsisAfterLines  number                 webkit-line-clamp 줄 수
 *      textAlign      CSS text-align
 *      fontWeight     "regular"|"medium"|"semibold"|"bold"   기본 "regular"
 *      color          string                      CSS 색상
 *      children, className, style, id 패스스루
 *
 *  · 서브들도 typography/fontWeight/color 등을 부분 오버라이드 가능 (자기만 다른 스타일).
 * ========================================================================== */

// ----- typography → utility class 매핑 -----
function __pgTypoClass(typo) {
  if (!typo || typeof typo !== "string") return "";
  let m = typo.match(/^t(\d+)$/i);
  if (m) {
    const n = parseInt(m[1], 10);
    if (n >= 1 && n <= 7) return `ty-${n}`;
  }
  m = typo.match(/^st(\d+)$/i);
  if (m) {
    const n = parseInt(m[1], 10);
    if (n >= 1 && n <= 13) return `sub-ty-${n}`;
  }
  if (window.console && console.warn) {
    console.warn(
      `[Paragraph] \`typography\` 는 t1~t7 또는 st1~st13 만 가능해요. 받은 값: ${typo}`
    );
  }
  return "";
}

// ----- fontWeight → utility class 매핑 -----
const __PG_FW_CLASS = {
  regular: "w-regular",
  medium: "w-medium",
  semibold: "w-semibold",
  bold: "w-bold",
};
function __pgFwClass(fw) {
  if (!fw) return "";
  return __PG_FW_CLASS[fw] || "";
}

// ----- 아이콘 URL 감지 -----
function __pgIsIconUrl(name) {
  if (!name) return false;
  return (
    /^(https?:|\/|\.{1,2}\/)/i.test(name) ||
    /\.(svg|png|jpe?g|gif|webp)(?:\?|#|$)/i.test(name)
  );
}
function __pgIsMonoIcon(name) {
  if (!name) return false;
  return /-mono(?:\.[^/?#]+)?(?:\?[^#]*)?(?:#.*)?$/i.test(name);
}

// =============================================================================
// Root Paragraph
// =============================================================================
function Paragraph({
  typography,
  display = "block",
  ellipsisAfterLines,
  textAlign,
  fontWeight = "regular",
  color,
  className = "",
  style,
  id,
  children,
  ...rest
}) {
  // typography 필수
  if (!typography) {
    if (window.console && console.warn) {
      console.warn("[Paragraph] `typography` 는 필수 prop 이에요.");
    }
  }

  const cls = [
    "tds-paragraph",
    display === "inline" ? "tds-paragraph--display-inline" : "",
    typeof ellipsisAfterLines === "number" && ellipsisAfterLines > 0
      ? "tds-paragraph--clamp"
      : "",
    __pgTypoClass(typography),
    __pgFwClass(fontWeight),
    className,
  ].filter(Boolean).join(" ");

  const mergedStyle = Object.assign({}, style || {});
  if (textAlign) mergedStyle.textAlign = textAlign;
  if (color) mergedStyle.color = color;
  if (typeof ellipsisAfterLines === "number" && ellipsisAfterLines > 0) {
    mergedStyle["--tds-paragraph-clamp"] = String(ellipsisAfterLines);
  }

  // display=inline 일 땐 root 도 inline 요소가 자연스러우니 <span>, 아니면 <p>
  const Tag = display === "inline" ? "span" : "p";

  return (
    <Tag id={id} className={cls} style={mergedStyle} {...rest}>
      {children}
    </Tag>
  );
}

// =============================================================================
// Paragraph.Text — 인라인 텍스트
// =============================================================================
function ParagraphText({
  typography,
  fontWeight,
  color,
  className = "",
  style,
  id,
  children,
  ...rest
}) {
  const cls = [
    "tds-paragraph__text",
    __pgTypoClass(typography),
    __pgFwClass(fontWeight),
    className,
  ].filter(Boolean).join(" ");

  const mergedStyle = color ? Object.assign({ color: color }, style || {}) : style;

  return (
    <span id={id} className={cls} style={mergedStyle} {...rest}>
      {children}
    </span>
  );
}

// =============================================================================
// Paragraph.Icon — 인라인 아이콘
// =============================================================================
function ParagraphIcon({
  name,
  mono,
  typography,        // 아이콘 높이 제어 — 부모와 다르게 줄 때
  className = "",
  style,
  id,
  ...rest
}) {
  if (!name) return null;

  const isUrl = __pgIsIconUrl(name);
  const inferredMono =
    typeof mono === "boolean" ? mono : (isUrl && __pgIsMonoIcon(name));

  const cls = [
    "tds-paragraph__icon",
    inferredMono ? "tds-paragraph__icon--mono" : "",
    __pgTypoClass(typography),
    className,
  ].filter(Boolean).join(" ");

  if (isUrl) {
    if (inferredMono) {
      const maskStyle = Object.assign(
        {
          WebkitMaskImage: `url("${name}")`,
          maskImage: `url("${name}")`,
        },
        style || {}
      );
      return (
        <span id={id} className={cls} style={maskStyle} aria-hidden="true" {...rest}>
          <img src={name} alt="" />
        </span>
      );
    }
    return (
      <span id={id} className={cls} style={style} aria-hidden="true" {...rest}>
        <img src={name} alt="" />
      </span>
    );
  }

  // IOSIcon 위임 — name 이 라이브러리 키
  if (window.IOSIcon) {
    return (
      <span id={id} className={cls} style={style} aria-hidden="true" {...rest}>
        <window.IOSIcon name={name} size="1em" />
      </span>
    );
  }
  return <span id={id} className={cls} style={style} aria-hidden="true" {...rest} />;
}

// =============================================================================
// Paragraph.Badge — 인라인 뱃지 (style fill/weak × type blue/teal/green/red/yellow/elephant)
// =============================================================================
const __PG_BADGE_VARIANTS = { fill: 1, weak: 1 };
const __PG_BADGE_COLORS = { blue: 1, teal: 1, green: 1, red: 1, yellow: 1, elephant: 1 };

// 스펙은 prop 명이 `style` (variant — fill/weak) 와 `type` (color — blue 등) 인데
// 일반 React 의 inline `style` 와 충돌하니, 스펙대로 받되 inline CSS 는 `htmlStyle` 로.
// `variant` 와 `color` 별칭도 동시에 받아서 사용 편의 ↑.
function ParagraphBadge({
  style,        // 스펙: "fill" | "weak"  (variant)
  type,         // 스펙: "blue" | "teal" | ... (color)
  variant,      // 별칭
  color,        // 별칭
  htmlStyle,    // 실제 inline CSS
  typography,
  className = "",
  id,
  children,
  ...rest
}) {
  const v = variant || style;
  const c = color || type;

  if (!__PG_BADGE_VARIANTS[v]) {
    if (window.console && console.warn) {
      console.warn(
        `[Paragraph.Badge] \`style\` (variant) 는 "fill" | "weak" 만 가능해요. 받은 값: ${v}`
      );
    }
  }
  if (!__PG_BADGE_COLORS[c]) {
    if (window.console && console.warn) {
      console.warn(
        `[Paragraph.Badge] \`type\` (color) 는 blue/teal/green/red/yellow/elephant 만 가능해요. 받은 값: ${c}`
      );
    }
  }
  const safeV = __PG_BADGE_VARIANTS[v] ? v : "weak";
  const safeC = __PG_BADGE_COLORS[c] ? c : "blue";

  const cls = [
    "tds-paragraph__badge",
    `tds-paragraph__badge--${safeV}-${safeC}`,
    __pgTypoClass(typography),
    className,
  ].filter(Boolean).join(" ");

  return (
    <span id={id} className={cls} style={htmlStyle} {...rest}>
      {children}
    </span>
  );
}

// =============================================================================
// Paragraph.Link — 인라인 링크 (type underline/clear, as 로 다른 태그)
// =============================================================================
function ParagraphLink({
  type = "clear",
  as,
  href,
  onClick,
  typography,
  fontWeight,
  color,
  className = "",
  style,
  id,
  children,
  ...rest
}) {
  const cls = [
    "tds-paragraph__link",
    type === "underline" ? "tds-paragraph__link--underline" : "tds-paragraph__link--clear",
    __pgTypoClass(typography),
    __pgFwClass(fontWeight),
    className,
  ].filter(Boolean).join(" ");

  const mergedStyle = Object.assign({}, style || {});
  if (color) mergedStyle.color = color;

  // as prop 처리 — 문자열이면 해당 태그, 아니면 a (href) / button
  let Tag;
  if (typeof as === "string") {
    Tag = as;
  } else if (typeof as === "function") {
    Tag = as;
  } else {
    Tag = href ? "a" : "button";
  }

  // button 으로 떨어지면 type="button" 명시 (form submit 방지)
  const tagProps = {};
  if (Tag === "a" && href) tagProps.href = href;
  if (Tag === "button") tagProps.type = tagProps.type || "button";

  return (
    <Tag
      id={id}
      className={cls}
      style={mergedStyle}
      onClick={onClick}
      {...tagProps}
      {...rest}
    >
      {children}
    </Tag>
  );
}

// ----- Subcomponent 부착 -----
Paragraph.Text = ParagraphText;
Paragraph.Icon = ParagraphIcon;
Paragraph.Badge = ParagraphBadge;
Paragraph.Link = ParagraphLink;

window.Paragraph = Paragraph;
window.ParagraphText = ParagraphText;
window.ParagraphIcon = ParagraphIcon;
window.ParagraphBadge = ParagraphBadge;
window.ParagraphLink = ParagraphLink;

Object.assign(window, {
  Paragraph,
  ParagraphText,
  ParagraphIcon,
  ParagraphBadge,
  ParagraphLink,
});
