function ProblemPlaceholder({ type }) {
  return (
    <div className={`landing-problem-visual is-${type || 'assets'}`} aria-hidden="true">
      <div className="problem-visual-stage" />
    </div>
  );
}

function renderProblemLines(text) {
  return String(text || '').split('\n').map((line, index) => (
    <React.Fragment key={`${line}-${index}`}>
      {index > 0 ? <br /> : null}
      {line}
    </React.Fragment>
  ));
}

function Problems() {
  const copy = window.atelaGetCopySection('problems');
  const cards = Array.isArray(copy.cards) ? copy.cards : [];
  const stackCount = cards.length;
  const flowRef = React.useRef(null);
  const progressRef = React.useRef(0);
  const snapLockRef = React.useRef(false);
  const snapTargetRef = React.useRef(null);
  const snapTimerRef = React.useRef(0);
  const [stackProgress, setStackProgress] = React.useState(0);

  React.useEffect(() => {
    const flow = flowRef.current;
    if (!flow) return undefined;

    let animationFrame = 0;

    const updateProgress = () => {
      animationFrame = 0;

      if (window.matchMedia?.('(max-width: 680px)').matches) {
        if (progressRef.current !== 0) {
          progressRef.current = 0;
          setStackProgress(0);
        }
        return;
      }

      const rect = flow.getBoundingClientRect();
      const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 1;
      const scrollDistance = Math.max(flow.offsetHeight - viewportHeight, 1);
      const rawProgress = Math.min(Math.max(-rect.top / scrollDistance, 0), 1);
      const maxProgress = Math.max(stackCount - 1, 0);
      const nextProgress = snapLockRef.current && snapTargetRef.current !== null
        ? snapTargetRef.current
        : (maxProgress ? Math.round(rawProgress * maxProgress) : 0);

      if (Math.abs(nextProgress - progressRef.current) > 0.006) {
        progressRef.current = nextProgress;
        setStackProgress(nextProgress);
      }
    };

    const requestUpdate = () => {
      if (animationFrame) return;
      animationFrame = window.requestAnimationFrame(updateProgress);
    };

    const releaseSnapLock = () => {
      snapLockRef.current = false;
      snapTargetRef.current = null;
      requestUpdate();
    };

    const handleWheel = (event) => {
      if (window.matchMedia?.('(max-width: 680px)').matches) return;
      if (stackCount <= 1) return;
      if (Math.abs(event.deltaY) <= Math.abs(event.deltaX)) return;

      const rect = flow.getBoundingClientRect();
      const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 1;
      const isInSnapRange = rect.top < viewportHeight * 0.55 && rect.bottom > viewportHeight * 0.45;

      if (!isInSnapRange) return;

      const maxProgress = stackCount - 1;
      const scrollDistance = Math.max(flow.offsetHeight - viewportHeight, 1);
      const rawProgress = Math.min(Math.max(-rect.top / scrollDistance, 0), 1);
      const direction = event.deltaY > 0 ? 1 : -1;

      if ((direction < 0 && rawProgress <= 0.02) || (direction > 0 && rawProgress >= 0.98)) {
        return;
      }

      event.preventDefault();

      if (snapLockRef.current) return;

      const currentIndex = Math.round(rawProgress * maxProgress);
      const nextIndex = Math.min(Math.max(currentIndex + direction, 0), maxProgress);
      const flowTop = window.scrollY + rect.top;
      const targetTop = flowTop + (nextIndex / maxProgress) * scrollDistance;
      const prefersReducedMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;

      snapLockRef.current = true;
      snapTargetRef.current = nextIndex;
      progressRef.current = nextIndex;
      setStackProgress(nextIndex);

      window.scrollTo({
        top: targetTop,
        behavior: prefersReducedMotion ? 'auto' : 'smooth',
      });

      if (snapTimerRef.current) {
        window.clearTimeout(snapTimerRef.current);
      }

      snapTimerRef.current = window.setTimeout(releaseSnapLock, 520);
    };

    updateProgress();
    window.addEventListener('scroll', requestUpdate, { passive: true });
    window.addEventListener('resize', requestUpdate);
    flow.addEventListener('wheel', handleWheel, { passive: false });

    return () => {
      window.removeEventListener('scroll', requestUpdate);
      window.removeEventListener('resize', requestUpdate);
      flow.removeEventListener('wheel', handleWheel);
      if (animationFrame) {
        window.cancelAnimationFrame(animationFrame);
      }
      if (snapTimerRef.current) {
        window.clearTimeout(snapTimerRef.current);
      }
    };
  }, [stackCount]);

  return (
    <section id="problems" className="landing-problems">
      <div className="atela-container">
        <div
          className="landing-problems-flow"
          ref={flowRef}
          style={{ '--stack-scroll-height': `${Math.max(stackCount, 1) * 64}vh` }}
          aria-label={copy.eyebrow || 'Problem cards'}
        >
          <div className="landing-problems-stage">
            <div className="landing-problems-head">
              <h2 className="atela-h2">{renderProblemLines(copy.headline)}</h2>
              <p className="landing-problems-intro">{copy.intro}</p>
            </div>

            <div className="landing-problems-track">
              {cards.map((card, i) => {
                const relation = i - stackProgress;
                const upcoming = Math.max(relation, 0);
                const passed = Math.max(-relation, 0);
                const cappedUpcoming = Math.min(upcoming, 1.08);
                const cappedPassed = Math.min(passed, 3);
                const cardY = 92 + cappedUpcoming * 330 - cappedPassed * 46;
                const cardScale = 1 - cappedPassed * 0.045 - Math.min(upcoming, 1) * 0.018;
                const cardOpacity = upcoming >= 0.98 ? 0 : 1;
                const contentOpacity = passed > 0 ? Math.max(0.34, 1 - passed / 0.42) : 1;
                const contentBlur = passed > 0 ? Math.min(2.4, passed * 4) : 0;

                return (
                  <article
                    key={`${card.quote || card.title || i}-${i}`}
                    className="landing-problem-card"
                    style={{
                      '--card-y': `${cardY}px`,
                      '--card-scale': String(cardScale),
                      '--card-opacity': String(cardOpacity),
                      '--card-content-opacity': String(contentOpacity),
                      '--card-content-blur': `${contentBlur}px`,
                      '--card-z': String(30 + i),
                      '--card-pointer': Math.abs(relation) < 0.62 ? 'auto' : 'none',
                    }}
                  >
                    <ProblemPlaceholder type={card.visual} />
                    <div className="landing-problem-card-copy">
                      <div className="landing-problem-meta">
                        <span className="landing-problem-number">{String(i + 1).padStart(2, '0')}</span>
                        <h3>{card.quote || card.title}</h3>
                      </div>
                      <p>{card.body}</p>
                    </div>
                  </article>
                );
              })}
            </div>
          </div>
        </div>

        {copy.transition ? (
          <div className="landing-problems-transition">
            {renderProblemLines(copy.transition)}
          </div>
        ) : null}
      </div>
    </section>
  );
}

window.Problems = Problems;
