// SwipeCard.jsx — One Tinder-style card. Pointer-drag right=yes, left=no,
// up=maybe, down=skip. Accessible keyboard arrows + explicit button row.
// Cards render different controls per `kind`: yesno | severity | chips | teeth | info.
const { useState: useSCs, useRef: useSCr, useEffect: useSCe } = React;

function SwipeCard({ card, value, onChange, onAnswer, mode = 'patient' }) {
  const ref = useSCr(null);
  const start = useSCr({ x: 0, y: 0, down: false });
  const [drag, setDrag] = useSCs({ x: 0, y: 0 });
  const [dir, setDir] = useSCs(null); // 'yes' | 'no' | 'maybe' | 'skip'

  const finish = (d) => {
    setDir(d);
    // exit animation
    const w = ref.current ? ref.current.getBoundingClientRect().width : 360;
    const exit = d === 'yes' ? { x: w * 1.5, y: 40 }
      : d === 'no' ? { x: -w * 1.5, y: 40 }
      : d === 'maybe' ? { x: 0, y: -w }
      : { x: 0, y: w };
    setDrag(exit);
    setTimeout(() => {
      onAnswer && onAnswer(d, value);
      setDir(null); setDrag({ x: 0, y: 0 });
    }, 220);
  };

  const handleKey = (e) => {
    if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
    if (e.key === 'ArrowRight') { e.preventDefault(); finish('yes'); }
    else if (e.key === 'ArrowLeft') { e.preventDefault(); finish('no'); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); finish('maybe'); }
    else if (e.key === 'ArrowDown') { e.preventDefault(); finish('skip'); }
  };

  // Cards that need value before advancing don't auto-finish on swipe yes;
  // we still allow swipe but use the captured `value` from controls.
  const onPointerDown = (e) => {
    if (e.target.closest('button, input, select, textarea, [data-no-drag]')) return;
    e.currentTarget.setPointerCapture(e.pointerId);
    start.current = { x: e.clientX, y: e.clientY, down: true };
  };
  const onPointerMove = (e) => {
    if (!start.current.down) return;
    const dx = e.clientX - start.current.x;
    const dy = e.clientY - start.current.y;
    setDrag({ x: dx, y: dy });
  };
  const onPointerUp = () => {
    if (!start.current.down) return;
    start.current.down = false;
    const { x, y } = drag;
    const w = ref.current ? ref.current.getBoundingClientRect().width : 360;
    const threshold = w * 0.32;
    if (x > threshold) return finish('yes');
    if (x < -threshold) return finish('no');
    if (y < -threshold) return finish('maybe');
    if (y > threshold) return finish('skip');
    setDrag({ x: 0, y: 0 });
  };

  const transform = dir
    ? `translate(${drag.x}px, ${drag.y}px) rotate(${drag.x * 0.06}deg)`
    : `translate(${drag.x}px, ${drag.y}px) rotate(${drag.x * 0.04}deg)`;

  const ghostYes  = drag.x > 30  ? Math.min(1, drag.x / 120) : 0;
  const ghostNo   = drag.x < -30 ? Math.min(1, -drag.x / 120) : 0;
  const ghostUp   = drag.y < -30 ? Math.min(1, -drag.y / 120) : 0;
  const ghostDown = drag.y > 30  ? Math.min(1, drag.y / 120) : 0;

  return (
    <div
      ref={ref}
      tabIndex={0}
      role="group"
      aria-roledescription="swipeable card"
      aria-label={card.prompt}
      onKeyDown={handleKey}
      onPointerDown={onPointerDown}
      onPointerMove={onPointerMove}
      onPointerUp={onPointerUp}
      onPointerCancel={onPointerUp}
      style={{
        position:'relative', userSelect:'none', touchAction:'pan-y',
        background:'var(--paper)', border:'1px solid var(--ink-5)', borderRadius:18,
        boxShadow:'0 12px 40px rgba(10,31,51,.10)',
        padding:'24px 22px', minHeight:340, width:'100%',
        transform, transition: dir ? 'transform .22s ease-out' : 'transform .14s ease-out',
        outline:'none', cursor:'grab',
        display:'flex', flexDirection:'column', gap:14,
      }}>
      {/* Ghost stamps */}
      <span style={{ position:'absolute', top:18, left:18, padding:'4px 10px', border:'2px solid var(--alert)', color:'var(--alert)', borderRadius:6, fontWeight:700, fontSize:12, letterSpacing:1, opacity:ghostNo, transform:'rotate(-12deg)' }}>NOPE</span>
      <span style={{ position:'absolute', top:18, right:18, padding:'4px 10px', border:'2px solid var(--sage)', color:'var(--sage)', borderRadius:6, fontWeight:700, fontSize:12, letterSpacing:1, opacity:ghostYes, transform:'rotate(12deg)' }}>YES</span>
      <span style={{ position:'absolute', top:48, left:'50%', transform:'translateX(-50%) rotate(-2deg)', padding:'4px 10px', border:'2px solid var(--seal)', color:'var(--seal)', borderRadius:6, fontWeight:700, fontSize:12, letterSpacing:1, opacity:ghostUp }}>MAYBE</span>
      <span style={{ position:'absolute', bottom:18, left:'50%', transform:'translateX(-50%) rotate(2deg)', padding:'4px 10px', border:'2px solid var(--ink-3)', color:'var(--ink-3)', borderRadius:6, fontWeight:700, fontSize:12, letterSpacing:1, opacity:ghostDown }}>SKIP</span>

      <div className="t-eyebrow" style={{ marginBottom:0 }}>{mode === 'clinician' ? 'Clinician triage' : 'Quick triage'} · card {card.id}</div>
      <h2 style={{ fontFamily:'var(--font-display)', fontWeight:500, fontSize:24, lineHeight:1.2, margin:0 }}>{card.prompt}</h2>
      {card.sub && <p style={{ margin:0, color:'var(--ink-2)', fontSize:14, lineHeight:1.55 }}>{card.sub}</p>}

      <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center', paddingTop:6 }} data-no-drag>
        <CardBody card={card} value={value} onChange={onChange}/>
      </div>

      <div role="group" aria-label="Answer choices" style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:8 }}>
        <button type="button" className="btn btn-secondary btn-sm" onClick={()=>finish('no')} aria-label="No (←)">← No</button>
        <button type="button" className="btn btn-tertiary btn-sm" onClick={()=>finish('maybe')} aria-label="Maybe (↑)">↑ Maybe</button>
        <button type="button" className="btn btn-tertiary btn-sm" onClick={()=>finish('skip')} aria-label="Skip (↓)">↓ Skip</button>
        <button type="button" className="btn btn-primary btn-sm" onClick={()=>finish('yes')} aria-label="Yes (→)">Yes →</button>
      </div>
    </div>
  );
}

function CardBody({ card, value, onChange }) {
  if (card.kind === 'yesno' || card.kind === 'info') {
    return <div style={{ color:'var(--ink-3)', fontSize:13, textAlign:'center' }}>{card.kind === 'info' ? 'Tap → to continue' : 'Swipe or tap a button'}</div>;
  }
  if (card.kind === 'severity') {
    const v = typeof value === 'number' ? value : 0;
    return (
      <div style={{ width:'100%' }}>
        <input type="range" min={card.min ?? 0} max={card.max ?? 10} value={v}
          onChange={(e)=>onChange && onChange(+e.target.value)}
          style={{ width:'100%' }} aria-label="Severity 0 to 10"/>
        <div style={{ display:'flex', justifyContent:'space-between', fontSize:11, color:'var(--ink-3)', marginTop:6 }}>
          <span>none</span><span style={{ fontWeight:700, color:'var(--ink-1)', fontSize:22 }}>{v}</span><span>worst</span>
        </div>
      </div>
    );
  }
  if (card.kind === 'chips') {
    const multi = !!card.multi;
    const selected = multi ? (Array.isArray(value) ? value : []) : value;
    const toggle = (slug) => {
      if (!onChange) return;
      if (multi) {
        const arr = Array.isArray(value) ? value : [];
        onChange(arr.includes(slug) ? arr.filter(x => x !== slug) : [...arr, slug]);
      } else {
        onChange(slug);
      }
    };
    return (
      <div style={{ display:'flex', flexWrap:'wrap', gap:8, justifyContent:'center' }}>
        {(card.chips || []).map(c => {
          const on = multi ? selected.includes(c.slug) : selected === c.slug;
          return (
            <button key={c.slug} type="button" onClick={()=>toggle(c.slug)}
              aria-pressed={on}
              style={{
                padding:'8px 14px', borderRadius:999, fontSize:13, fontWeight:500, cursor:'pointer',
                background: on ? 'var(--ink-1)' : 'var(--paper)',
                color: on ? 'var(--paper)' : 'var(--ink-1)',
                border: `1px solid ${on ? 'var(--ink-1)' : 'var(--ink-5)'}`,
              }}>{c.label}</button>
          );
        })}
      </div>
    );
  }
  if (card.kind === 'teeth') {
    const data = (value && typeof value === 'object') ? value : {};
    const teeth = Object.keys(data).map(n => +n);
    const update = ({ teeth: t, toothPain: tp }) => {
      const next = {};
      t.forEach(n => { next[n] = tp[n] ?? 5; });
      onChange && onChange(next);
    };
    if (window.ToothChart) {
      return <div style={{ width:'100%' }}><window.ToothChart teeth={teeth} toothPain={data} onChange={update} size="sm"/></div>;
    }
    return <div style={{ color:'var(--ink-3)' }}>Tooth chart loading…</div>;
  }
  return null;
}

window.SwipeCard = SwipeCard;
