// ─────────────────────────────────────────────────────────────
// GITWRAP — card + overlay components
// ─────────────────────────────────────────────────────────────

const CARD_W = 600, CARD_H = 315, PAD = 28;
const OVERLAY_W = 405, OVERLAY_H = 720;

// --- sparkline (shared) ------------------------------------------
function Sparkline({ series, active, delay, accent, width, height = 44, filled = true }) {
  const pathRef = useRef(null);
  const [len, setLen] = useState(0);
  const [drawn, setDrawn] = useState(false);

  const W = width;
  const H = height;
  const pts = series.map((v, i) => {
    const x = series.length === 1 ? W / 2 : (i / (series.length - 1)) * W;
    const y = H - 4 - v * (H - 10);
    return [x, y];
  });
  const d = pts.map((p, i) => `${i ? 'L' : 'M'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const area = `M0,${H} L` + pts.map((p) => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' L') + ` L${W},${H} Z`;

  useLayoutEffect(() => {
    if (pathRef.current) setLen(pathRef.current.getTotalLength());
  }, [d]);

  useEffect(() => {
    if (active && len) {
      const t = setTimeout(() => setDrawn(true), delay);
      return () => clearTimeout(t);
    }
    setDrawn(false);
  }, [active, len, delay]);

  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} style={{ display: 'block', overflow: 'visible' }}>
      <defs>
        <linearGradient id="spark-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={accent} stopOpacity="0.28" />
          <stop offset="100%" stopColor={accent} stopOpacity="0.02" />
        </linearGradient>
      </defs>
      {filled && (
        <path d={area} fill="url(#spark-fill)"
          style={{ opacity: drawn ? 1 : 0, transition: 'opacity 700ms ease 200ms' }} />
      )}
      <path ref={pathRef} d={d} fill="none" stroke={accent} strokeWidth="2.5"
        strokeLinejoin="round" strokeLinecap="round"
        style={{
          strokeDasharray: len, strokeDashoffset: drawn ? 0 : len,
          transition: 'stroke-dashoffset 820ms cubic-bezier(0.16,1,0.3,1)',
          filter: `drop-shadow(0 0 5px ${accent}99)`,
        }} />
      {pts.map((p, i) => (
        <circle key={i} cx={p[0]} cy={p[1]} r="2.8" fill={filled ? 'var(--surface)' : 'rgba(0,0,0,0.6)'} stroke={accent} strokeWidth="1.8"
          style={{
            opacity: drawn ? 1 : 0,
            transform: drawn ? 'scale(1)' : 'scale(0)',
            transformOrigin: `${p[0]}px ${p[1]}px`,
            transition: `opacity 200ms ease, transform 260ms cubic-bezier(0.34,1.56,0.64,1)`,
            transitionDelay: `${820 + i * 26}ms`,
          }} />
      ))}
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────
// CARD FORMAT (landscape 600×315, dark bg with photo overlay)
// ─────────────────────────────────────────────────────────────

function StatTile({ tile, active, delay, big }) {
  const value = useCountUp(tile.value, active, { delay: delay + 140 });
  return (
    <div style={{
      flex: 1, minWidth: 0,
      padding: '12px 14px', borderRadius: 10,
      background: 'rgba(9,12,16,0.52)',
      border: '1px solid rgba(255,255,255,0.08)',
      opacity: active ? 1 : 0,
      transform: active ? 'translateY(0)' : 'translateY(10px)',
      transition: 'opacity 220ms ease, transform 280ms var(--ease-out)',
      transitionDelay: `${delay}ms`,
    }}>
      <div style={{
        fontSize: 10, letterSpacing: '0.10em', textTransform: 'uppercase',
        color: 'rgba(240,246,252,0.5)', fontWeight: 500, marginBottom: 6, whiteSpace: 'nowrap',
      }}>{tile.label}</div>
      <div className="mono tnum" style={{
        fontSize: big ? 30 : 34, fontWeight: 800, lineHeight: 1, color: 'var(--white)',
        letterSpacing: '-0.03em', textShadow: '0 2px 12px rgba(0,0,0,0.6)',
      }}>{fmt(value)}</div>
    </div>
  );
}

function ShimmerTiles() {
  return (
    <div style={{ display: 'flex', gap: 10, width: '100%' }}>
      {[0, 1, 2].map((i) => (
        <div key={i} style={{
          flex: 1, padding: '12px 14px', borderRadius: 10,
          background: 'rgba(9,12,16,0.45)', border: '1px solid rgba(255,255,255,0.06)',
        }}>
          <div className="gw-shimmer" style={{ height: 10, width: '56%', borderRadius: 3, marginBottom: 10 }} />
          <div className="gw-shimmer" style={{ height: 28, width: '80%', borderRadius: 5 }} />
        </div>
      ))}
    </div>
  );
}

function Card({ stats, phase, patUnlocked, error, exportRef }) {
  const active = phase === 'reveal';
  const accent = 'var(--green)';

  const tiles = stats ? [...stats.tiles] : [];
  if (patUnlocked && stats) tiles.push({ key: 'loc', label: 'Lines of Code', value: stats.loc });

  const tileBase = 200, tileStep = 80;
  const sparkDelay = tileBase + tiles.length * tileStep + 100;
  const footerDelay = sparkDelay + 900;
  const avatarUrl = stats?.avatar || '';

  return (
    <div ref={exportRef} style={{
      width: CARD_W, height: CARD_H, position: 'relative',
      borderRadius: 14, overflow: 'hidden', background: '#090c10',
      boxShadow: '0 32px 80px -20px rgba(0,0,0,0.9), 0 0 0 1px rgba(255,255,255,0.07)',
    }}>
      {avatarUrl && (
        <img src={avatarUrl} crossOrigin="anonymous" alt="" style={{
          position: 'absolute', inset: 0, width: '100%', height: '100%',
          objectFit: 'cover', objectPosition: 'center top',
          filter: 'blur(3px) brightness(0.38) saturate(1.4)',
          transform: 'scale(1.05)',
        }} />
      )}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'linear-gradient(to bottom, rgba(9,12,16,0.60) 0%, rgba(9,12,16,0.10) 38%, rgba(9,12,16,0.0) 55%, rgba(9,12,16,0.55) 78%, rgba(9,12,16,0.82) 100%)',
        zIndex: 1,
      }} />
      <div style={{
        position: 'absolute', top: -80, left: '50%', transform: 'translateX(-50%)',
        width: 500, height: 220, zIndex: 1, pointerEvents: 'none',
        background: 'radial-gradient(closest-side, rgba(63,185,80,0.12), transparent)',
      }} />

      {phase === 'error' ? (
        <div style={{
          position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center', gap: 10, padding: PAD, zIndex: 3,
        }}>
          <div className="mono" style={{ fontSize: 30, color: 'var(--green)', lineHeight: 1 }}>×</div>
          <div className="mono" style={{ fontSize: 16, color: 'var(--white)' }}>{error?.title || 'user not found'}</div>
          <div style={{ fontSize: 13, color: 'var(--muted)' }}>{error?.sub || 'check the username and try again'}</div>
        </div>
      ) : (
        <div style={{ position: 'absolute', inset: 0, padding: PAD, display: 'flex', flexDirection: 'column', zIndex: 3 }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 13 }}>
              <div style={{
                width: 44, height: 44, borderRadius: '50%', flexShrink: 0,
                overflow: 'hidden', border: '2px solid rgba(63,185,80,0.5)',
                background: 'rgba(9,12,16,0.6)',
                opacity: active ? 1 : (phase === 'loading' ? 0.5 : 0),
                transform: active ? 'scale(1)' : 'scale(0.7)',
                transition: 'opacity 220ms ease, transform 300ms cubic-bezier(0.34,1.56,0.64,1)',
                transitionDelay: '30ms',
              }}>
                {avatarUrl && <img src={avatarUrl} crossOrigin="anonymous" alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />}
              </div>
              <div style={{
                opacity: active ? 1 : 0,
                transform: active ? 'translateX(0)' : 'translateX(-10px)',
                transition: 'opacity 240ms ease, transform 280ms var(--ease-out)', transitionDelay: '70ms',
              }}>
                <div className="mono" style={{ fontSize: 18, fontWeight: 700, color: '#fff', letterSpacing: '-0.01em', textShadow: '0 2px 16px rgba(0,0,0,0.8)', lineHeight: 1.15 }}>
                  {stats?.name || stats?.username}
                </div>
                <div style={{ fontSize: 11.5, marginTop: 3, color: 'rgba(240,246,252,0.6)', display: 'flex', alignItems: 'center', gap: 5 }}>
                  <span style={{ color: 'var(--green)', fontSize: 7 }}>●</span>
                  {stats?.topLang} · most active language
                </div>
              </div>
            </div>
            <div style={{
              opacity: active ? 1 : 0, transform: active ? 'translateX(0)' : 'translateX(10px)',
              transition: 'opacity 240ms ease, transform 280ms var(--ease-out)', transitionDelay: '110ms',
            }}>
              <span className="mono" style={{
                fontSize: 11, fontWeight: 600, color: 'var(--green)',
                background: 'rgba(9,12,16,0.55)', border: '1px solid rgba(63,185,80,0.45)',
                padding: '5px 12px', borderRadius: 999, letterSpacing: '0.07em', textTransform: 'uppercase',
              }}>{stats?.range.label}</span>
            </div>
          </div>

          <div style={{ flex: 1, display: 'flex', alignItems: 'flex-end', paddingBottom: 2 }}>
            {phase === 'loading' ? <ShimmerTiles /> : (
              <div style={{ display: 'flex', gap: 10, width: '100%' }}>
                {tiles.map((t, i) => (
                  <StatTile key={t.key} tile={t} active={active} big={tiles.length > 3} delay={tileBase + i * tileStep} />
                ))}
              </div>
            )}
          </div>

          <div style={{ marginTop: 10 }}>
            {phase === 'loading' ? (
              <div className="gw-shimmer" style={{ height: 44, borderRadius: 6 }} />
            ) : (
              <Sparkline series={stats?.series || []} active={active} delay={sparkDelay} accent={accent} width={CARD_W - PAD * 2} filled />
            )}
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8 }}>
              <span className="mono" style={{ fontSize: 10.5, color: 'rgba(240,246,252,0.40)', opacity: active ? 1 : 0, transition: 'opacity 300ms ease', transitionDelay: `${footerDelay}ms` }}>
                github.com/{stats?.username}
              </span>
              <span className="mono" style={{ fontSize: 10.5, color: 'rgba(240,246,252,0.40)', letterSpacing: '0.05em', opacity: active ? 1 : 0, transition: 'opacity 300ms ease', transitionDelay: `${footerDelay}ms` }}>
                {stats?.range.axis} · gitwrap
              </span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// OVERLAY FORMAT (portrait 405×720, transparent bg)
// Designed to be layered over any photo in IG/TikTok/etc.
// ─────────────────────────────────────────────────────────────

function OverlayCard({ stats, patUnlocked, exportRef }) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => { const t = setTimeout(() => setMounted(true), 60); return () => clearTimeout(t); }, []);

  const active = mounted;
  const accent = '#3fb950';

  const tiles = stats ? [...stats.tiles] : [];
  if (patUnlocked && stats) tiles.push({ key: 'loc', label: 'Lines of Code', value: stats.loc });

  const tileBase = 80, tileStep = 90;
  const sparkDelay = tileBase + tiles.length * tileStep + 60;
  const footerDelay = sparkDelay + 900;
  const OW = OVERLAY_W - 48; // inner width

  return (
    <div ref={exportRef} style={{
      width: OVERLAY_W, height: OVERLAY_H, position: 'relative',
      background: 'transparent', overflow: 'hidden',
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      padding: '0 24px',
      fontFamily: "'Geist Mono', 'Geist', ui-monospace, monospace",
    }}>
      {/* stat rows */}
      <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
        {tiles.map((t, i) => (
          <OverlayStatRow key={t.key} tile={t} active={active} delay={tileBase + i * tileStep} />
        ))}
      </div>

      {/* sparkline */}
      <div style={{
        marginTop: 28, width: '100%',
        opacity: active ? 1 : 0, transition: 'opacity 400ms ease', transitionDelay: `${sparkDelay}ms`,
      }}>
        <Sparkline series={stats?.series || []} active={active} delay={sparkDelay} accent={accent} width={OW} height={52} filled={false} />
      </div>

      {/* GitHub logo + range */}
      <div style={{
        marginTop: 28, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
        opacity: active ? 1 : 0, transition: 'opacity 300ms ease', transitionDelay: `${footerDelay}ms`,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <svg viewBox="0 0 16 16" width="28" height="28" fill="white" style={{ filter: 'drop-shadow(0 2px 8px rgba(0,0,0,0.7))' }}>
            <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
          </svg>
          <span style={{
            fontSize: 26, fontWeight: 700, color: 'white', letterSpacing: '-0.01em',
            textShadow: '0 2px 20px rgba(0,0,0,0.9)',
          }}>GitHub</span>
        </div>
        <span style={{
          fontSize: 13, color: 'rgba(255,255,255,0.45)', letterSpacing: '0.06em',
          textShadow: '0 1px 8px rgba(0,0,0,0.8)', textTransform: 'uppercase',
        }}>{stats?.range.sub} · gitwrap</span>
      </div>
    </div>
  );
}

function OverlayStatRow({ tile, active, delay }) {
  const value = useCountUp(tile.value, active, { delay: delay + 100 });
  return (
    <div style={{
      textAlign: 'center', width: '100%',
      opacity: active ? 1 : 0,
      transform: active ? 'translateY(0)' : 'translateY(14px)',
      transition: 'opacity 300ms ease, transform 360ms cubic-bezier(0.16,1,0.3,1)',
      transitionDelay: `${delay}ms`,
    }}>
      <div style={{
        fontSize: 13, fontWeight: 500, letterSpacing: '0.12em', textTransform: 'uppercase',
        color: 'rgba(255,255,255,0.55)',
        textShadow: '0 1px 12px rgba(0,0,0,0.9)',
        marginBottom: 2,
      }}>{tile.label}</div>
      <div style={{
        fontSize: 76, fontWeight: 800, lineHeight: 1, color: 'white',
        letterSpacing: '-0.04em', fontVariantNumeric: 'tabular-nums',
        fontFamily: "'Geist Mono', ui-monospace, monospace",
        textShadow: '0 4px 32px rgba(0,0,0,0.95), 0 0 60px rgba(0,0,0,0.6)',
      }}>{fmt(value)}</div>
    </div>
  );
}

Object.assign(window, { Card, OverlayCard, Sparkline, StatTile, CARD_W, CARD_H, OVERLAY_W, OVERLAY_H });
