(() => {
  const OriginalCarousel = window.LCS?.Carousel;
  if (!OriginalCarousel || window.LCS.__carouselPeekOverrideInstalled) return;

  const { Icon } = window.LCS;

  const openSpecifications = (event) => {
    const description = event.currentTarget.closest(".pdp")?.querySelector(".pdp__description");
    const target = Array.from(description?.querySelectorAll("[data-md-title]") || [])
      .find((element) => element.dataset.mdTitle === "商品仕様");
    if (!target) return;
    for (let current = target; current && current !== description; current = current.parentElement) {
      if (current.tagName === "DETAILS") current.open = true;
    }
    const headerOffset = document.querySelector(".header")?.offsetHeight || 0;
    window.scrollTo({ top: Math.max(0, target.getBoundingClientRect().top + window.scrollY - headerOffset - 18), behavior: "smooth" });
  };

  const getYouTubeId = (url = "") => {
    if (!/^https?:\/\//.test(url)) return "";
    try {
      const parsed = new URL(url);
      const host = parsed.hostname.replace(/^www\./, "");
      if (host === "youtu.be") return parsed.pathname.split("/").filter(Boolean)[0] || "";
      if (!/(^|\.)youtube\.com$/.test(host)) return "";
      if (parsed.pathname === "/watch") return parsed.searchParams.get("v") || "";
      const match = parsed.pathname.match(/^\/(?:embed|shorts)\/([^/?#]+)/);
      return match ? match[1] : "";
    } catch {
      return "";
    }
  };

  const getSlideMedia = (slide = {}) => {
    const youtubeId = getYouTubeId(slide.src);
    if (!youtubeId) return { type: "image", src: slide.src, alt: slide.alt || "" };
    return {
      type: "youtube",
      id: youtubeId,
      src: `https://www.youtube.com/embed/${youtubeId}?fs=0`,
      thumb: slide.thumb || `https://img.youtube.com/vi/${youtubeId}/hqdefault.jpg`,
      alt: slide.alt || "YouTube動画",
    };
  };

  const SlideImage = ({ slide }) => {
    const media = getSlideMedia(slide);
    return <img src={media.type === "youtube" ? media.thumb : media.src} alt={media.alt} />;
  };

  const SlideMedia = ({ slide }) => {
    const media = getSlideMedia(slide);
    const [loadedSrc, setLoadedSrc] = React.useState("");
    const isLoaded = loadedSrc === media.src;

    React.useEffect(() => {
      setLoadedSrc("");
    }, [media.src]);

    if (media.type !== "youtube") return <img src={media.src} alt={media.alt} />;

    return (
      <div className={"carousel__video" + (isLoaded ? " is-loaded" : "")}>
        {!isLoaded && (
          <div className="carousel__video-loading" aria-hidden="true">
            <img src={media.thumb} alt="" />
            <span className="carousel__video-spinner" />
          </div>
        )}
        <iframe
          src={media.src}
          title={media.alt}
          onLoad={() => setLoadedSrc(media.src)}
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
          loading="lazy"
        />
      </div>
    );
  };

  const EnhancedCarousel = ({ slides, autoplay = false, interval = 6500, go, ruleLink }) => {
    const [idx, setIdx] = React.useState(0);
    const [paused, setPaused] = React.useState(false);
    const [fullscreen, setFullscreen] = React.useState(false);
    const n = slides.length;

    React.useEffect(() => {
      if (!autoplay || paused || fullscreen || n <= 1 || getSlideMedia(slides[idx]).type === "youtube") return;
      const t = setInterval(() => setIdx((i) => (i + 1) % n), interval);
      return () => clearInterval(t);
    }, [autoplay, paused, fullscreen, n, interval, idx, slides]);

    React.useEffect(() => {
      if (!fullscreen) return;
      const prevOverflow = document.body.style.overflow;
      document.body.style.overflow = "hidden";
      const onKeyDown = (e) => {
        if (e.key === "Escape") setFullscreen(false);
      };
      window.addEventListener("keydown", onKeyDown);
      return () => {
        document.body.style.overflow = prevOverflow;
        window.removeEventListener("keydown", onKeyDown);
      };
    }, [fullscreen]);

    const goTo = (i) => setIdx(((i % n) + n) % n);
    const s = slides[idx];
    const currentMedia = getSlideMedia(s);

    const followSlide = (e, href) => {
      if (!go || !href?.startsWith("/")) return;
      const [route, id] = href.replace(/^\//, "").split("/");
      e.preventDefault();
      go(route || "home", id);
    };

    // フル表示するサムネイルは常に最大3枚。
    // その外側に前後のスライドがある場合だけ、細いプレビューを左右端へ出す。
    const visCount = Math.min(3, n);
    const half = Math.floor(visCount / 2);
    const winStart = Math.max(0, Math.min(idx - half, n - visCount));
    const visibleThumbs = slides.slice(winStart, winStart + visCount);
    const prevPeekIndex = winStart > 0 ? winStart - 1 : null;
    const nextPeekIndex = winStart + visCount < n ? winStart + visCount : null;
    const hasPeekRail = n > visCount;

    const renderThumb = (slide, actualIdx, extraClass = "") => (
      <button
        key={`${extraClass || "full"}-${actualIdx}`}
        className={"carousel__thumb" + (extraClass ? ` ${extraClass}` : "") + (actualIdx === idx ? " active" : "")}
        onClick={() => setIdx(actualIdx)}
        aria-label={`slide ${actualIdx + 1}`}
        type="button"
      >
        <SlideImage slide={slide} />
        {getSlideMedia(slide).type === "youtube" && <span className="carousel__thumb-play">▶</span>}
      </button>
    );

    return (
      <div
        className={"carousel" + (fullscreen && currentMedia.type === "youtube" ? " carousel--video-expanded" : "")}
        onMouseEnter={() => setPaused(true)}
        onMouseLeave={() => setPaused(false)}
      >
        <div className="carousel__main">
          <div className="carousel__media-frame">
          {s.href && currentMedia.type === "image"
            ? <a href={s.href} onClick={(e) => followSlide(e, s.href)}><SlideMedia slide={s} /></a>
            : <SlideMedia slide={s} />}
          </div>
          {(ruleLink || go) && (
            <div className="carousel__linkbar">
              {s.caption ? (
                <p className="carousel__caption">{s.caption}</p>
              ) : ruleLink ? (
                <div className="carousel__link-actions">
                  <button className="carousel__rule-link" onClick={ruleLink.onClick} type="button">{ruleLink.label}</button>
                  <button className="carousel__rule-link carousel__spec-link" onClick={openSpecifications} type="button">商品仕様を見る</button>
                </div>
              ) : (
                <button className="carousel__rule-link carousel__rule-link--hero" onClick={(e) => followSlide(e, s.href)} type="button">商品を見る</button>
              )}
              <button className="carousel__fullscreen" onClick={() => setFullscreen(true)} type="button" aria-label={currentMedia.type === "youtube" ? "動画を全画面表示" : "画像を全画面表示"}>
                <Icon name="expand" size={18} />
              </button>
            </div>
          )}
        </div>

        {n > 1 && (
          <div className="carousel__strip">
            <button className="carousel__strip-nav" onClick={() => goTo(idx - 1)} aria-label="前のサムネイル" type="button">
              <Icon name="chev-l" size={16} />
            </button>

            {hasPeekRail ? (
              <div className="carousel__thumbs carousel__thumbs--peek">
                {prevPeekIndex !== null
                  ? renderThumb(slides[prevPeekIndex], prevPeekIndex, "carousel__thumb--peek carousel__thumb--peek-prev")
                  : <span className="carousel__thumb-peek-spacer" aria-hidden="true" />}

                {visibleThumbs.map((thumb, i) => renderThumb(thumb, winStart + i, "carousel__thumb--full"))}

                {nextPeekIndex !== null
                  ? renderThumb(slides[nextPeekIndex], nextPeekIndex, "carousel__thumb--peek carousel__thumb--peek-next")
                  : <span className="carousel__thumb-peek-spacer" aria-hidden="true" />}
              </div>
            ) : (
              <div className="carousel__thumbs" style={{ gridTemplateColumns: `repeat(${visCount}, minmax(0, 1fr))` }}>
                {visibleThumbs.map((thumb, i) => renderThumb(thumb, winStart + i, "carousel__thumb--full"))}
              </div>
            )}

            <button className="carousel__strip-nav" onClick={() => goTo(idx + 1)} aria-label="次のサムネイル" type="button">
              <Icon name="chev-r" size={16} />
            </button>
          </div>
        )}

        {!ruleLink && !go && <button
          className="carousel__fullscreen carousel__fullscreen--floating"
          onClick={() => setFullscreen(true)}
          type="button"
          aria-label={currentMedia.type === "youtube" ? "動画を全画面表示" : "画像を全画面表示"}
        >
          <Icon name="expand" size={18} />
        </button>}

        {fullscreen && currentMedia.type === "image" && (
          <div className="media-viewer" role="dialog" aria-modal="true">
            <div className="media-viewer__frame">
              <img className="media-viewer__image" src={currentMedia.src} alt={currentMedia.alt} />
            </div>
          </div>
        )}

        {fullscreen && n > 1 && (
          <>
            <button className="media-viewer__nav media-viewer__nav--prev" onClick={() => goTo(idx - 1)} type="button" aria-label="前のスライド">
              <Icon name="chev-l" size={26} />
            </button>
            <button className="media-viewer__nav media-viewer__nav--next" onClick={() => goTo(idx + 1)} type="button" aria-label="次のスライド">
              <Icon name="chev-r" size={26} />
            </button>
            <div className="media-viewer__counter" aria-live="polite">{idx + 1} / {n}</div>
          </>
        )}

        {fullscreen && (
          <button className="carousel__video-close media-viewer__close" onClick={() => setFullscreen(false)} type="button" aria-label="閉じる">
            <Icon name="x" size={22} />
          </button>
        )}
      </div>
    );
  };

  const originalCreateElement = React.createElement;
  React.createElement = function (type, props, ...children) {
    const resolvedType = type === OriginalCarousel ? EnhancedCarousel : type;
    return originalCreateElement.call(React, resolvedType, props, ...children);
  };

  window.LCS.Carousel = EnhancedCarousel;
  window.LCS.__carouselPeekOverrideInstalled = true;
})();
