// Services — scroll-driven horizontal card strip
//
// ASSET FLAGS:
// - File names use spaces ("branding 1.jpg"), not hyphens as specified. Paths match actual files.
// - Motion card: no YouTube URL found — using local "assets/services/motion.mp4" instead.
// - Strategy: only 2 images found (strategy 1.jpg, strategy 2.jpg). No third image.

const SERVICES = [
  {
    title: "Branding",
    tags: ["Logo design", "Typography", "Color system", "Brand guidelines", "Business cards", "Brand identity"],
    media: { type: "carousel", images: [
      "assets/services/branding 1.jpg",
      "assets/services/branding 2.jpg",
      "assets/services/branding 3.jpg",
    ]},
  },
  {
    title: "Web & Product",
    tags: ["Landing pages", "SaaS UI", "Design systems", "Component libraries", "UX audit", "Prototyping"],
    media: { type: "carousel", images: [
      "assets/services/web and product 1.avif",
      "assets/services/web and product 2.avif",
      "assets/services/web and product 3.avif",
    ]},
  },
  {
    title: "Graphic Design",
    tags: ["Marketing materials", "Presentations", "Social assets", "Print design", "Infographics", "Packaging"],
    media: { type: "carousel", images: [
      "assets/services/graphic design 1.jpg",
      "assets/services/graphic design 2.jpg",
      "assets/services/graphic design 3.jpg",
    ]},
  },
  {
    title: "Motion",
    tags: ["Micro-interactions", "Animated assets", "Video graphics", "UI animations", "Loading states"],
    media: { type: "video", src: "assets/services/motion.mp4" },
  },
  {
    title: "Strategy",
    tags: ["Brand positioning", "UX strategy", "Design direction", "Competitive audit", "Roadmapping"],
    media: { type: "carousel", images: [
      "assets/services/strategy 1.jpg",
      "assets/services/strategy 2.jpg",
    ]},
  },
  {
    title: "& More",
    desc: "Additional support across formats, channels, and disciplines — wherever the work takes us.",
    tags: ["3D & Illustration", "Print Design", "Email Templates", "Pitch Decks", "Iconography", "UI Audits", "Copywriting", "Infographics"],
  },
];

// ─── CardCarousel ─────────────────────────────────────────────
// Controlled by parent state; notifies parent of index changes via onIdxChange
const CardCarousel = ({ images, idx = 0, onIdxChange }) => {
  const idxRef  = React.useRef(idx);
  const dragRef = React.useRef({ active: false, startX: 0 });
  const total   = images.length;

  const go = (n) => {
    const next = ((n % total) + total) % total;
    idxRef.current = next;
    onIdxChange && onIdxChange(next);
  };

  React.useEffect(() => {
    idxRef.current = idx;
  }, [idx]);

  React.useEffect(() => {
    const onUp = (e) => {
      if (!dragRef.current.active) return;
      const endX = e.clientX ?? e.changedTouches?.[0]?.clientX ?? dragRef.current.startX;
      const delta = endX - dragRef.current.startX;
      if (Math.abs(delta) > 40) go(idxRef.current + (delta < 0 ? 1 : -1));
      dragRef.current.active = false;
    };
    window.addEventListener("mouseup",  onUp);
    window.addEventListener("touchend", onUp, { passive: true });
    return () => {
      window.removeEventListener("mouseup",  onUp);
      window.removeEventListener("touchend", onUp);
    };
  }, []);

  const onDown = (x) => { dragRef.current = { active: true, startX: x }; };

  return (
    <div
      className="ag-carousel"
      data-no-track-drag="true"
      onMouseDown={(e) => { e.preventDefault(); onDown(e.clientX); }}
      onTouchStart={(e) => onDown(e.touches[0].clientX)}
    >
      <div
        className="ag-carousel__strip"
        style={{ transform: `translateX(-${idx * 100}%)` }}
      >
        {images.map((src, i) => (
          <img key={i} src={src} alt="" className="ag-carousel__img" draggable="false" />
        ))}
      </div>
    </div>
  );
};

// ─── CardVideo ────────────────────────────────────────────────
const CardVideo = ({ src }) => {
  const videoRef = React.useRef(null);
  const [playing, setPlaying] = React.useState(false);

  const toggle = (e) => {
    e.stopPropagation();
    const v = videoRef.current;
    if (!v) return;
    if (playing) { v.pause(); } else { v.play(); }
    setPlaying(!playing);
  };

  return (
    <div className="ag-card-video" data-no-track-drag="true" onMouseDown={(e) => e.stopPropagation()}>
      <video
        ref={videoRef}
        src={src}
        playsInline
        loop
        className="ag-card-video__el"
        onEnded={() => setPlaying(false)}
      />
      <button className="ag-card-video__btn" onClick={toggle} type="button" aria-label={playing ? "Pause" : "Play"}>
        {playing ? (
          <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
            <rect x="5" y="4" width="4" height="16" rx="1"/>
            <rect x="15" y="4" width="4" height="16" rx="1"/>
          </svg>
        ) : (
          <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
            <polygon points="7,3 21,12 7,21"/>
          </svg>
        )}
      </button>
    </div>
  );
};

// ─── ServiceCard ──────────────────────────────────────────────
const ServiceCard = ({ title, desc, tags, media, num }) => {
  const isCarousel = media?.type === "carousel";
  const isVideo    = media?.type === "video";
  const total      = isCarousel ? media.images.length : 0;

  const [carouselIdx, setCarouselIdx] = React.useState(0);

  React.useEffect(() => {
    if (!isCarousel || total <= 1) return;
    const cardOrder = Number.parseInt(num, 10) || 1;
    const intervalMs = 2800 + (cardOrder % 5) * 350;
    const startDelayMs = (cardOrder % 4) * 220;

    let timerId = null;
    const startInterval = () => {
      timerId = window.setInterval(() => {
        setCarouselIdx((prev) => (prev + 1) % total);
      }, intervalMs);
    };

    let bootId = null;
    if (startDelayMs > 0) {
      bootId = window.setTimeout(() => {
        setCarouselIdx((prev) => (prev + 1) % total);
        startInterval();
      }, startDelayMs);
    } else {
      startInterval();
    }

    return () => {
      if (bootId) window.clearTimeout(bootId);
      if (timerId) window.clearInterval(timerId);
    };
  }, [isCarousel, total, num]);

  const goNext = React.useCallback(() => {
    if (!isCarousel || total <= 1) return;
    setCarouselIdx((prev) => (prev + 1) % total);
  }, [isCarousel, total]);

  const cls = [
    "ag-services-card",
    media ? "ag-services-card--media" : "ag-services-card--text",
    isVideo ? "ag-services-card--video" : "",
  ].filter(Boolean).join(" ");

  return (
    <article
      className={cls}
      data-no-track-drag={isCarousel ? "true" : undefined}
      onClick={isCarousel ? goNext : undefined}
    >
      {media && (
        <div className="ag-services-card__media">
          {isCarousel && <CardCarousel images={media.images} idx={carouselIdx} onIdxChange={setCarouselIdx} />}
          {isVideo    && <CardVideo src={media.src} />}
        </div>
      )}
      <div className="ag-services-card__body">
        <span className="ag-services-card__num">{num}</span>
        {isCarousel && total > 1 && (
          <div className="ag-carousel__dots">
            {media.images.map((_, i) => (
              <button
                key={i}
                type="button"
                className={"ag-carousel__dot" + (i === carouselIdx ? " is-active" : "")}
                onClick={(e) => { e.stopPropagation(); setCarouselIdx(i); }}
                aria-label={`Go to ${title} image ${i + 1}`}
                aria-current={i === carouselIdx ? "true" : "false"}
              />
            ))}
          </div>
        )}
        <h3 className="ag-services-card__title">{title}</h3>
        {desc && <p className="ag-services-card__desc">{desc}</p>}
        <div className="ag-services-card__tags">
          {tags.map((t) => (
            <span key={t} className="ag-chip ag-chip--light">{t}</span>
          ))}
        </div>
      </div>
    </article>
  );
};

// ─── Services ─────────────────────────────────────────────────
const Services = ({ data, lang }) => {
  const hasSection = data !== null && data !== undefined;
  const services = hasSection
    ? (Array.isArray(data) ? [...data].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)).map(s => ({
        title: i18(s.title, lang) || '',
        desc:  i18(s.desc, lang)  || '',
        tags:  (i18(s.tags, lang) || '').split(',').map(t => t.trim()).filter(Boolean),
        media: s.cardType === 'video' && s.mediaSrc
          ? { type: 'video', src: s.mediaSrc }
          : Array.isArray(s.mediaImages) && s.mediaImages.length
          ? { type: 'carousel', images: s.mediaImages }
          : s.mediaImage
          ? { type: 'carousel', images: [s.mediaImage] }
          : null,
      })) : [])
    : (window.TRANSLATIONS?.services?.items || SERVICES).map((_, i) => ({
        title: t('services.items.' + i + '.title', lang),
        desc:  t('services.items.' + i + '.desc',  lang) || '',
        tags:  t('services.items.' + i + '.tags', lang).split(',').map(x => x.trim()).filter(Boolean),
        media: SERVICES[i]?.media || null,
      }));

  const sectionRef = React.useRef(null);
  const trackRef   = React.useRef(null);
  const wrapRef    = React.useRef(null);
  const rafRef     = React.useRef(null);
  const setupRef   = React.useRef(null); // expose setup so CMS data changes can retrigger it

  const isMobile = () => window.innerWidth <= 960;

  // Scroll-driven horizontal translate
  React.useEffect(() => {
    const section = sectionRef.current;
    const track   = trackRef.current;
    const wrap    = wrapRef.current;
    if (!section || !track || !wrap) return;

    let maxTranslate = 0;
    let enabled = false;

    const setup = () => {
      enabled = !isMobile();
      if (!enabled) {
        section.style.height = "";
        track.style.transform = "";
        return;
      }
      maxTranslate = Math.max(0, track.scrollWidth - wrap.offsetWidth);
      section.style.height = (window.innerHeight + maxTranslate) + "px";
    };

    setupRef.current = setup; // keep ref current so the effect below can call it

    const onScroll = () => {
      if (!enabled) return;
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      rafRef.current = requestAnimationFrame(() => {
        const sectionTop = section.getBoundingClientRect().top + window.scrollY;
        const scrollable = parseFloat(section.style.height) - window.innerHeight;
        if (scrollable <= 0) return;
        const progress = Math.max(0, Math.min(1, (window.scrollY - sectionTop) / scrollable));
        track.style.transform = `translateX(${-progress * maxTranslate}px)`;
      });
    };

    const onResize = () => { setup(); onScroll(); };

    setup();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onResize);

    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onResize);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, []);

  // When CMS changes the card count, maxTranslate and section height become stale.
  // Re-run setup() so both are recalculated against the updated track.scrollWidth.
  React.useEffect(() => {
    setupRef.current?.();
  }, [services.length]);

  // Track drag — skips if pointer is inside a carousel or video
  React.useEffect(() => {
    const track = trackRef.current;
    const wrap  = wrapRef.current;
    if (!track || !wrap) return;
    if (isMobile()) return;

    let dragging    = false;
    let startX      = 0;
    let startTransX = 0;

    const getTransX = () => new DOMMatrix(getComputedStyle(track).transform).m41;
    const clamp = (v) => Math.max(-(track.scrollWidth - wrap.offsetWidth), Math.min(0, v));

    const onDown = (x) => {
      dragging = true;
      startX = x;
      startTransX = getTransX();
      track.classList.add("is-dragging");
      track.style.transition = "none";
    };

    const onMove = (x) => {
      if (!dragging) return;
      track.style.transform = `translateX(${clamp(startTransX + x - startX)}px)`;
    };

    const onUp = () => {
      if (!dragging) return;
      dragging = false;
      track.classList.remove("is-dragging");
    };

    const isInsideCard = (e) => !!e.target.closest("[data-no-track-drag]");

    const onMouseMove = (e) => { if (dragging) { e.preventDefault(); onMove(e.clientX); } };
    const onTouchMove = (e) => onMove(e.touches[0].clientX);
    const onMouseDown = (e) => { if (!isInsideCard(e)) onDown(e.clientX); };
    const onTouchStart = (e) => { if (!isInsideCard(e)) onDown(e.touches[0].clientX); };

    track.addEventListener("mousedown",  onMouseDown);
    window.addEventListener("mousemove", onMouseMove);
    window.addEventListener("mouseup",   onUp);
    track.addEventListener("touchstart", onTouchStart, { passive: true });
    track.addEventListener("touchmove",  onTouchMove, { passive: true });
    track.addEventListener("touchend",   onUp);

    return () => {
      track.removeEventListener("mousedown", onMouseDown);
      track.removeEventListener("touchstart", onTouchStart);
      track.removeEventListener("touchmove", onTouchMove);
      track.removeEventListener("touchend", onUp);
      window.removeEventListener("mousemove", onMouseMove);
      window.removeEventListener("mouseup",   onUp);
    };
  }, []);

  return (
    <section className="ag-services" id="ag-section-services" ref={sectionRef}>
      <div className="ag-services__sticky">
        <div className="ag-services__head">
          <SectionHeading
            eyebrow={t('services.eyebrow', lang)}
            align="start"
            sub={t('services.sub', lang)}
          >
            {t('services.heading', lang)}
          </SectionHeading>
        </div>
        <div className="ag-services__track-wrap" ref={wrapRef}>
          <div className="ag-services__track" ref={trackRef}>
            {services.map((s, i) => (
              <ServiceCard
                key={s.title}
                num={String(i + 1).padStart(2, "0")}
                {...s}
              />
            ))}
          </div>
        </div>
      </div>
    </section>
  );
};

window.Services = Services;
