// card-reader.jsx — refined editorial card reader
// Fixed card, inner scroll, vertical swipe between stories.

const CardReader = ({ index, setIndex, onClose, soundOn, stories }) => {
  const list = stories || STORIES;
  const story = list[index];
  const total = list.length;
  const bodyRef = React.useRef(null);
  const [drag, setDrag] = React.useState(0);
  const [dir, setDir] = React.useState(0);
  const [transitioning, setTransitioning] = React.useState(false);
  const [bouncing, setBouncing] = React.useState(false);
  const start = React.useRef(null);
  const lastSwipe = React.useRef(0);

  const rustle = React.useCallback(() => {
    if (!soundOn) return;
    try {
      const ctx = new (window.AudioContext || window.webkitAudioContext)();
      const buf = ctx.createBuffer(1, ctx.sampleRate * 0.22, ctx.sampleRate);
      const data = buf.getChannelData(0);
      for (let i = 0; i < data.length; i++) {
        const t = i / data.length;
        data[i] = (Math.random() * 2 - 1) * (1 - t) * 0.22 * Math.sin(t * 40);
      }
      const src = ctx.createBufferSource();
      src.buffer = buf;
      const hp = ctx.createBiquadFilter();
      hp.type = 'highpass'; hp.frequency.value = 1800;
      const g = ctx.createGain(); g.gain.value = 0.3;
      src.connect(hp).connect(g).connect(ctx.destination);
      src.start();
      src.onended = () => ctx.close();
    } catch(e) {}
  }, [soundOn]);

  const bounceIt = () => { setBouncing(true); setTimeout(() => setBouncing(false), 280); };

  const goNext = React.useCallback(() => {
    if (index >= total - 1) { bounceIt(); return; }
    rustle(); setDir(1); setTransitioning(true);
    setTimeout(() => { setIndex(i => Math.min(total - 1, i + 1)); setDir(0); setTransitioning(false); }, 280);
  }, [index, total, rustle, setIndex]);

  const goPrev = React.useCallback(() => {
    if (index <= 0) { bounceIt(); return; }
    rustle(); setDir(-1); setTransitioning(true);
    setTimeout(() => { setIndex(i => Math.max(0, i - 1)); setDir(0); setTransitioning(false); }, 280);
  }, [index, rustle, setIndex]);

  React.useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = 0; }, [index]);

  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === ' ') { e.preventDefault(); goNext(); }
      else if (e.key === 'ArrowUp' || e.key === 'PageUp') { e.preventDefault(); goPrev(); }
      else if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [goNext, goPrev, onClose]);

  const onTouchStart = (e) => {
    if (transitioning) return;
    const el = bodyRef.current;
    const t = e.touches[0];
    start.current = { y: t.clientY, activated: false };
  };
  const onTouchMove = (e) => {
    if (!start.current || transitioning) return;
    const t = e.touches[0];
    const dy = t.clientY - start.current.y;
    const el = bodyRef.current;
    const atTop = el.scrollTop <= 0;
    const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
    const pullDown = dy > 0 && atTop;
    const pullUp = dy < 0 && atBottom;
    if (start.current.activated || pullDown || pullUp) {
      start.current.activated = true;
      setDrag(Math.max(-180, Math.min(180, dy)));
    } else setDrag(0);
  };
  const onTouchEnd = () => {
    if (!start.current) return;
    const dy = drag;
    const threshold = 80;
    const now = Date.now();
    if (now - lastSwipe.current < 350) { setDrag(0); start.current = null; return; }
    if (dy < -threshold) { lastSwipe.current = now; goNext(); }
    else if (dy > threshold) { lastSwipe.current = now; goPrev(); }
    setDrag(0);
    start.current = null;
  };

  React.useEffect(() => {
    const el = bodyRef.current;
    if (!el) return;
    const onWheel = (e) => {
      if (transitioning) return;
      const atTop = el.scrollTop <= 0;
      const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 1;
      const now = Date.now();
      if (now - lastSwipe.current < 700) return;
      if (e.deltaY > 30 && atBottom) { lastSwipe.current = now; goNext(); }
      else if (e.deltaY < -30 && atTop) { lastSwipe.current = now; goPrev(); }
    };
    el.addEventListener('wheel', onWheel, { passive: true });
    return () => el.removeEventListener('wheel', onWheel);
  }, [goNext, goPrev, transitioning]);

  const displayAuthor = story.authorEn || story.author;
  const displayAuthorSubline = story.authorEn ? story.author : '';
  let cardTransform = `translateY(${drag}px)`;
  let cardOpacity = 1;
  if (transitioning) {
    cardTransform = dir === 1 ? 'translateY(-100%)' : 'translateY(100%)';
    cardOpacity = 0;
  }
  if (bouncing) cardTransform = `translateY(${drag > 0 ? 12 : -12}px)`;

  // Monogram initials
  const initials = displayAuthor.split(/\s+/).map(w => w[0]).slice(0, 2).join('').toUpperCase();

  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 100, background: 'rgba(20,16,10,0.3)', animation: 'fade-up 220ms ease' }}>
      <div
        className="card-stack paper-bg"
        style={{
          transform: cardTransform, opacity: cardOpacity,
          transition: (transitioning || (!start.current && !bouncing))
            ? 'transform 280ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 280ms' : 'none',
          display: 'flex', flexDirection: 'column',
        }}
      >
        {/* Header */}
        <div style={{
          padding: '14px 18px 12px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          borderBottom: '1px solid rgba(31,26,19,0.12)',
          background: 'rgba(245,239,224,0.85)',
          backdropFilter: 'blur(8px)',
        }}>
          <button onClick={onClose} style={{
            background: 'transparent', border: 'none', padding: 6,
            display: 'flex', alignItems: 'center', gap: 6,
            color: 'var(--ink)', cursor: 'pointer',
            fontFamily: 'Inter, sans-serif', fontSize: 13, fontWeight: 500,
          }}>
            <svg width="14" height="14" viewBox="0 0 20 20" fill="none"><path d="M13 4L6 10l7 6" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
            Index
          </button>

          <div style={{ textAlign: 'center' }}>
            <div className="kicker" style={{ fontSize: 9 }}>LETTER</div>
            <div className="display" style={{ fontSize: 18, color: 'var(--ink)', lineHeight: 1, marginTop: 2, fontWeight: 500 }}>
              {String(index + 1).padStart(2, '0')}<span style={{ color: 'var(--ink-dim)', fontWeight: 400 }}> / {String(total).padStart(2, '0')}</span>
            </div>
          </div>

          <div className="mono" style={{ fontSize: 9, color: 'var(--ink-dim)', letterSpacing: '0.12em' }}>
            {story.date.split(',')[0]}
          </div>
        </div>

        {/* Body */}
        <div ref={bodyRef} className="story-body"
             onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}>

          {/* Monogram + author */}
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14, marginBottom: 24 }}>
            <div style={{
              width: 56, height: 56, borderRadius: 28,
              background: 'var(--ink)', color: 'var(--paper)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: 'Fraunces, serif', fontSize: 20, fontWeight: 500, fontStyle: 'italic',
              flexShrink: 0, letterSpacing: '-0.02em',
            }}>{initials}</div>
            <div style={{ flex: 1, minWidth: 0, paddingTop: 2 }}>
              <div className="display" style={{ fontSize: 24, color: 'var(--ink)', fontWeight: 500, lineHeight: 1.1 }}>
                {displayAuthor}
              </div>
              {displayAuthorSubline && (
                <div style={{ fontSize: 13, color: 'var(--ink-dim)', marginTop: 5, fontStyle: 'italic' }}>
                  {displayAuthorSubline}
                </div>
              )}
              <div style={{ fontSize: 12, color: 'var(--ink-soft)', marginTop: 4 }}>
                {story.role} · <span style={{ fontStyle: 'italic', color: 'var(--ink-dim)' }}>{story.group}</span>
              </div>
            </div>
          </div>

          {/* Pull-quote / opening mark */}
          <div style={{
            borderLeft: '2px solid var(--coral)',
            paddingLeft: 14, marginBottom: 18,
          }}>
            <div className="body-text" style={{
              fontSize: 17, color: 'var(--ink)', fontStyle: 'italic',
              fontWeight: 500, lineHeight: 1.45,
            }}>
              {story.body[0]}
            </div>
          </div>

          {/* Remaining paragraphs */}
          <div className="body-text" style={{ fontSize: 15, color: 'var(--ink)', lineHeight: 1.72 }}>
            {story.body.slice(1).map((p, i) => (
              <p key={i} style={{ margin: '0 0 14px' }}>{p}</p>
            ))}
          </div>

          {/* Divider + end-mark */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, margin: '32px 0 14px' }}>
            <hr className="hr-fine" style={{ flex: 1 }}/>
            <div className="mono" style={{ fontSize: 9, letterSpacing: '0.3em', color: 'var(--ink-dim)' }}>
              {String(index + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}
            </div>
            <hr className="hr-fine" style={{ flex: 1 }}/>
          </div>

          {/* Next cue */}
          <div style={{ textAlign: 'center', marginTop: 8, marginBottom: 20 }}>
            {index < total - 1 ? (
              <>
                <div className="kicker" style={{ color: 'var(--ink-dim)' }}>SWIPE UP FOR</div>
                <div className="display" style={{ fontSize: 20, color: 'var(--coral)', marginTop: 6, fontStyle: 'italic', fontWeight: 500 }}>
                  {list[index + 1].authorEn || list[index + 1].author}
                </div>
              </>
            ) : (
              <div className="display" style={{ fontSize: 18, color: 'var(--ink-soft)', fontStyle: 'italic', fontWeight: 400 }}>
                — fin —
              </div>
            )}
          </div>
        </div>

        <div style={{
          padding: '12px 18px 18px',
          display: 'grid',
          gridTemplateColumns: '1fr 1fr',
          gap: 10,
          borderTop: '1px solid rgba(31,26,19,0.12)',
          background: 'rgba(245,239,224,0.92)',
          backdropFilter: 'blur(8px)',
        }}>
          <button
            onClick={goPrev}
            disabled={index <= 0}
            style={{
              minHeight: 44,
              borderRadius: 999,
              border: '1px solid rgba(31,26,19,0.12)',
              background: index <= 0 ? 'rgba(31,26,19,0.06)' : 'rgba(255,253,247,0.92)',
              color: index <= 0 ? 'var(--ink-dim)' : 'var(--ink)',
              cursor: index <= 0 ? 'default' : 'pointer',
              fontFamily: 'DM Sans, sans-serif',
              fontSize: 13,
              fontWeight: 600,
            }}
          >
            Previous
          </button>
          <button
            onClick={goNext}
            disabled={index >= total - 1}
            style={{
              minHeight: 44,
              borderRadius: 999,
              border: 'none',
              background: index >= total - 1 ? 'rgba(31,26,19,0.12)' : 'var(--coral)',
              color: index >= total - 1 ? 'var(--ink-dim)' : 'var(--paper)',
              cursor: index >= total - 1 ? 'default' : 'pointer',
              fontFamily: 'DM Sans, sans-serif',
              fontSize: 13,
              fontWeight: 600,
              boxShadow: index >= total - 1 ? 'none' : '0 4px 10px rgba(232,90,62,0.28)',
            }}
          >
            {index >= total - 1 ? 'No More Letters' : 'Next Letter'}
          </button>
        </div>

        {/* Side progress rail */}
        <div className="progress-rail">
          <div className="progress-fill" style={{ height: `${((index + 1) / total) * 100}%` }}/>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { CardReader });
