/* ============================================================
   INDIC LEAGUE NEWS — Card Stack with full swipe physics
   - Axis lock on first 6px (h vs v)
   - Drag transform = translate(dx,0) rotate(dx*0.065deg)
   - Threshold |dx| > 90 → fly-off; below → spring snap-back
   - Left swipe = next; Right swipe = previous (per plan F06)
   - tappedFab flag prevents FAB taps from triggering tap-to-open
   - Web Audio sounds + Vibration haptics on transitions
   ============================================================ */

function ArticleCard({ article, isActive, onTapBody, onTapShare, onTapLike, onTapSave, onTapSkip, liked, saved, cardRef, onPointerDown }) {
  // FABs need to NOT propagate as drag/tap. We set a marker on the card body.
  const fabClick = (e, fn) => {
    e.stopPropagation();
    fn && fn();
  };

  return (
    <article
      className="card"
      ref={cardRef}
      onPointerDown={onPointerDown}
      aria-label={article.headline}
    >
      <div className="card-hero">
        <img src={article.image} alt="" draggable="false" />
        <div className="card-badge">{article.badge}</div>
        <div className="card-time">{article.publishedAt}</div>
      </div>
      <div className="card-body">
        <div className="card-meta">
          <span className="card-category">{article.category}</span>
          {article.politicalConfidence >= 0.4 && (
            <span className="card-political">{article.politicalLabel}</span>
          )}
        </div>
        <h2 className="card-headline">{article.headline}</h2>
        <p className="card-summary">{article.summary}</p>
        <div className="card-byline">
          <div className="byline-avatar">
            {article.authorAvatar
              ? <img src={article.authorAvatar} alt="" />
              : article.author.split(' ').map(w => w[0]).join('').slice(0, 2)}
          </div>
          <span className="byline-name">By {article.author}</span>
        </div>
      </div>
    </article>
  );
}

function GhostCard({ offset = 1, tint = 'peach' }) {
  const transform = `translateY(${offset * 8}px) scale(${1 - offset * 0.035}) rotate(${offset === 1 ? -2.4 : 2.4}deg)`;
  return (
    <div
      className={'card card-ghost ' + (tint === 'peach' ? 'peach' : '')}
      style={{ transform, zIndex: 1 - offset, opacity: 1 - offset * 0.18 }}
      aria-hidden="true"
    />
  );
}

/* ============================================================
   The stack
   ============================================================ */
function CardStack({ articles, onOpenArticle, likedIds, savedIds, onLike, onSave, onShare, onRead }) {
  const [idx, setIdx] = React.useState(0);
  const [animating, setAnimating] = React.useState(false);
  const [overlay, setOverlay] = React.useState(null); // 'next' | 'prev' | null
  const [popFab, setPopFab] = React.useState(null);   // 'like' | 'save' | 'skip' | null

  const cardRef = React.useRef(null);
  const dragRef = React.useRef({
    active: false,
    lockedAxis: null,
    startX: 0,
    startY: 0,
    dx: 0,
    dy: 0,
    tappedFab: false,
    pointerId: null,
  });

  const len = articles.length;
  const current = articles[idx % len];

  // Card entrance animation
  const [entering, setEntering] = React.useState(true);
  React.useEffect(() => {
    setEntering(true);
    const t = setTimeout(() => setEntering(false), 50);
    return () => clearTimeout(t);
  }, [idx]);

  // Notify parent on each new active article
  React.useEffect(() => {
    if (current && onRead) onRead(current);
    // eslint-disable-next-line
  }, [current && current.id]);

  // --- gesture helpers ---
  const setCardTransform = (dx, dy = 0) => {
    if (!cardRef.current) return;
    const rot = dx * 0.06;
    cardRef.current.style.transform = `translate(${dx}px, ${dy * 0.3}px) rotate(${rot}deg)`;
    cardRef.current.style.transition = 'none';
  };

  const flyOff = (dir) => {
    if (!cardRef.current) return;
    setAnimating(true);
    setOverlay(dir > 0 ? 'next' : 'prev');
    window.IL_Sounds && window.IL_Sounds.swipeCommit(dir);
    window.IL_Util && window.IL_Util.Haptics.swipeCommit();
    cardRef.current.style.transition = 'transform 400ms cubic-bezier(0.55, 0, 1, 0.45), opacity 400ms';
    cardRef.current.style.transform = `translate(${dir * 140}%, 0) rotate(${dir * 22}deg)`;
    cardRef.current.style.opacity = '0';
    setTimeout(() => {
      // Advance/retreat in stack
      setIdx((i) => dir > 0 ? (i + 1) % len : (i - 1 + len) % len);
      setOverlay(null);
      setAnimating(false);
      if (cardRef.current) {
        cardRef.current.style.transition = 'none';
        cardRef.current.style.transform = '';
        cardRef.current.style.opacity = '';
      }
    }, 380);
  };

  const snapBack = () => {
    if (!cardRef.current) return;
    setAnimating(true);
    window.IL_Sounds && window.IL_Sounds.snapback();
    cardRef.current.style.transition = 'transform 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275)';
    cardRef.current.style.transform = 'translate(0,0) rotate(0deg)';
    setTimeout(() => {
      setAnimating(false);
      if (cardRef.current) cardRef.current.style.transition = 'none';
    }, 480);
  };

  // --- pointer handlers (axis lock on first 6px) ---
  const onPointerDown = (e) => {
    if (animating) return;
    // Ignore if target is inside .fab-row (handled below) or has data-no-drag
    if (e.target.closest('[data-no-drag]')) return;

    dragRef.current = {
      active: true, lockedAxis: null,
      startX: e.clientX, startY: e.clientY,
      dx: 0, dy: 0, tappedFab: false,
      pointerId: e.pointerId,
    };
    e.currentTarget.setPointerCapture(e.pointerId);
  };

  const onPointerMove = (e) => {
    const s = dragRef.current;
    if (!s.active) return;
    const dx = e.clientX - s.startX;
    const dy = e.clientY - s.startY;
    s.dx = dx; s.dy = dy;

    if (!s.lockedAxis) {
      const adx = Math.abs(dx), ady = Math.abs(dy);
      if (adx < 6 && ady < 6) return;       // still in dead zone
      s.lockedAxis = adx > ady ? 'h' : 'v';
    }

    if (s.lockedAxis === 'h') {
      setCardTransform(dx, dy);
      // Light tick haptic when crossing threshold
      const past = Math.abs(dx) > 90;
      if (past && !s.haptedAt90) {
        s.haptedAt90 = true;
        window.IL_Util && window.IL_Util.Haptics.light();
        setOverlay(dx > 0 ? 'prev' : 'next');
      } else if (!past && s.haptedAt90) {
        s.haptedAt90 = false;
        setOverlay(null);
      }
    }
  };

  const onPointerUp = (e) => {
    const s = dragRef.current;
    if (!s.active) return;
    s.active = false;

    // Tap detection: never locked, OR axis locked but trivial movement
    const isTap = s.lockedAxis === null && Math.abs(s.dx) < 8 && Math.abs(s.dy) < 8;
    if (isTap) {
      // Only fire if not on FAB and not sponsored
      onOpenArticle && onOpenArticle(current);
      return;
    }

    if (s.lockedAxis === 'h' && Math.abs(s.dx) > 90) {
      // Left swipe = next (dir = +1 → advance)
      // Right swipe = previous (dir = -1 → retreat)
      const dir = s.dx < 0 ? 1 : -1;
      flyOff(dir);
    } else {
      setOverlay(null);
      snapBack();
    }
  };

  // --- Programmatic actions (also exposed on FABs) ---
  const goNext = () => { if (!animating) flyOff(1); };
  const goPrev = () => { if (!animating) flyOff(-1); };

  const onLikeClick = () => {
    setPopFab('like');
    window.IL_Sounds && window.IL_Sounds.like();
    window.IL_Util && window.IL_Util.Haptics.medium();
    onLike && onLike(current);
    setTimeout(() => setPopFab(null), 280);
  };
  const onSaveClick = () => {
    setPopFab('save');
    window.IL_Sounds && window.IL_Sounds.save();
    window.IL_Util && window.IL_Util.Haptics.light();
    onSave && onSave(current);
    setTimeout(() => setPopFab(null), 280);
  };
  const onSkipClick = () => {
    setPopFab('skip');
    window.IL_Util && window.IL_Util.Haptics.light();
    goNext();
    setTimeout(() => setPopFab(null), 280);
  };
  const onShareClick = () => {
    setPopFab('share');
    window.IL_Sounds && window.IL_Sounds.tap();
    window.IL_Util && window.IL_Util.Haptics.light();
    onShare && onShare(current);
    setTimeout(() => setPopFab(null), 280);
  };
  const onPrimaryClick = () => {
    setPopFab('flame');
    window.IL_Sounds && window.IL_Sounds.swipeCommit(1);
    window.IL_Util && window.IL_Util.Haptics.medium();
    goNext();
    setTimeout(() => setPopFab(null), 280);
  };

  // Keyboard nav
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'ArrowLeft')  goPrev();
      if (e.key === 'ArrowRight') goNext();
      if (e.key === 'l' || e.key === 'L') onLikeClick();
      if (e.key === 's' || e.key === 'S') onSaveClick();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
    // eslint-disable-next-line
  }, [animating, current && current.id]);

  if (!current) return null;
  const isLiked = likedIds && likedIds.has(current.id);
  const isSaved = savedIds && savedIds.has(current.id);

  return (
    <>
      <div className="cardstack">
        <GhostCard offset={2} tint="peach" />
        <GhostCard offset={1} tint="default" />

        <article
          className="card"
          ref={cardRef}
          onPointerDown={onPointerDown}
          onPointerMove={onPointerMove}
          onPointerUp={onPointerUp}
          onPointerCancel={onPointerUp}
          style={{
            zIndex: 5,
            animation: entering ? 'none' : undefined,
            transform: entering ? 'translateY(52px) scale(0.94) rotate(-1deg)' : '',
            opacity: entering ? 0.6 : 1,
            transition: entering ? 'none' : 'transform 600ms cubic-bezier(0.34, 1.42, 0.64, 1), opacity 400ms',
            touchAction: 'pan-y',
            cursor: 'grab',
            userSelect: 'none',
            WebkitUserSelect: 'none',
          }}
        >
          <div className="card-hero">
            <img src={current.image} alt="" draggable="false" />
            <div className="card-badge">{current.badge}</div>
            <div className="card-time">{current.publishedAt}</div>
          </div>
          <div className="card-body">
            <div className="card-meta">
              <span className="card-category">{current.category}</span>
              {current.politicalConfidence >= 0.4 && (
                <span className="card-political">{current.politicalLabel}</span>
              )}
            </div>
            <h2 className="card-headline">{current.headline}</h2>
            <p className="card-summary">{current.summary}</p>
            <div className="card-byline">
              <div className="byline-avatar">
                {current.authorAvatar
                  ? <img src={current.authorAvatar} alt="" />
                  : current.author.split(' ').map(w => w[0]).join('').slice(0, 2)}
              </div>
              <span className="byline-name">By {current.author}</span>
            </div>
          </div>

          {/* Swipe direction overlay */}
          <div className={'swipe-overlay ' + (overlay || '')} style={{ opacity: overlay ? 1 : 0 }}>
            {overlay === 'next' && (
              <div className="swipe-overlay-pill">
                <Icon name="arrow-right" size={28} stroke={2.4} color="#fff" />
                <span>NEXT</span>
              </div>
            )}
            {overlay === 'prev' && (
              <div className="swipe-overlay-pill">
                <Icon name="check-thick" size={28} stroke={2.6} color="#fff" />
                <span>PREVIOUS</span>
              </div>
            )}
          </div>
        </article>
      </div>

      {/* Progress dots */}
      <div className="card-progress" style={{ marginTop: 14, justifyContent: 'center' }}>
        <div className="card-progress-dots">
          {articles.slice(0, Math.min(len, 8)).map((_, i) => (
            <span
              key={i}
              className={'card-progress-dot' + (i === idx % Math.min(len, 8) ? ' active' : '')}
            />
          ))}
          {len > 8 && (
            <span style={{ marginLeft: 6, fontSize: 10, color: 'var(--text-3)', fontWeight: 600 }}>
              +{len - 8}
            </span>
          )}
        </div>
      </div>

      {/* FABs */}
      <div className="fab-row" data-no-drag>
        <button
          className={'fab' + (popFab === 'skip' ? ' fab-popped' : '')}
          aria-label="Skip"
          onClick={onSkipClick}
        >
          <Icon name="x" size={20} stroke={2} />
        </button>
        <button
          className={'fab' + (popFab === 'save' ? ' fab-popped' : '') + (isSaved ? ' fab-liked' : '')}
          aria-label="Save"
          onClick={onSaveClick}
        >
          <Icon name="bookmark" size={20} stroke={1.8} fill={isSaved ? 'currentColor' : 'none'} />
        </button>
        <button
          className={'fab fab-primary' + (popFab === 'flame' ? ' fab-popped' : '')}
          aria-label="Next story"
          onClick={onPrimaryClick}
        >
          <Icon name="flame" size={24} stroke={2.2} color="#fff" fill="rgba(255,255,255,0.18)" />
        </button>
        <button
          className={'fab' + (popFab === 'share' ? ' fab-popped' : '')}
          aria-label="Share"
          onClick={onShareClick}
        >
          <Icon name="share" size={20} stroke={1.8} />
        </button>
        <button
          className={'fab' + (popFab === 'like' ? ' fab-popped' : '') + (isLiked ? ' fab-liked' : '')}
          aria-label="Like"
          onClick={onLikeClick}
        >
          <Icon name="heart" size={20} stroke={1.8} fill={isLiked ? 'currentColor' : 'none'} />
        </button>
      </div>

      <div className="swipe-hint">
        <Icon name="hand-up" size={14} stroke={1.6} />
        Swipe left for next, or tap to read full story
      </div>
    </>
  );
}

Object.assign(window, { CardStack, ArticleCard, GhostCard });
