// Shared atoms for the PROVE prototype.
// Landing + web app share these. Some have web-app-specific variants.

const { useState, useMemo, useEffect, useRef } = React;

// ── Logo wordmark ───────────────────────────────────────────────
function ProveLogo({ size = 22, color, weight = 800, tracking = -0.04 }) {
  return (
    <span style={{
      fontFamily: 'var(--display)',
      fontWeight: weight,
      fontSize: size,
      letterSpacing: `${tracking}em`,
      color: color || 'currentColor',
      textTransform: 'uppercase',
      lineHeight: 1,
      display: 'inline-flex',
      alignItems: 'center',
      gap: size * 0.18,
    }}>
      <span style={{
        width: size * 0.36,
        height: size * 0.36,
        background: 'var(--coral)',
        display: 'inline-block',
        borderRadius: 2,
        transform: 'rotate(45deg)',
      }} />
      PROVE
    </span>
  );
}

// ── BlurTile ─ abstract gradient + noise as a blurred-video still.
function BlurTile({ hue = 20, seed = 0, label, aspect = '4/5', radius = 0, style }) {
  const s = (n) => ((Math.sin(seed * 9.13 + n * 2.7) + 1) / 2);
  const b1x = 10 + s(1) * 70, b1y = 10 + s(2) * 70;
  const b2x = 10 + s(3) * 70, b2y = 10 + s(4) * 70;
  const b3x = 10 + s(5) * 70, b3y = 10 + s(6) * 70;
  const lightness = 32 + s(7) * 8;
  const accentHue = (hue + (s(8) * 60 - 30) + 360) % 360;

  const bg = `
    radial-gradient(60% 50% at ${b1x}% ${b1y}%, oklch(${lightness + 18}% 0.14 ${accentHue}) 0%, transparent 60%),
    radial-gradient(45% 45% at ${b2x}% ${b2y}%, oklch(${lightness + 8}% 0.10 ${(hue + 180) % 360}) 0%, transparent 65%),
    radial-gradient(70% 60% at ${b3x}% ${b3y}%, oklch(${lightness + 22}% 0.16 ${hue}) 0%, transparent 55%),
    linear-gradient(${seed * 47}deg, oklch(${lightness - 4}% 0.06 ${hue}), oklch(${lightness + 4}% 0.08 ${(hue + 40) % 360}))
  `;

  return (
    <div style={{
      position: 'relative',
      aspectRatio: aspect,
      width: '100%',
      borderRadius: radius,
      background: bg,
      overflow: 'hidden',
      isolation: 'isolate',
      ...style,
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'180\' height=\'180\'><filter id=\'n\'><feTurbulence type=\'fractalNoise\' baseFrequency=\'1.8\' numOctaves=\'2\' stitchTiles=\'stitch\'/><feColorMatrix values=\'0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.45 0\'/></filter><rect width=\'100%\' height=\'100%\' filter=\'url(%23n)\'/></svg>")',
        backgroundSize: '180px 180px',
        mixBlendMode: 'overlay',
        opacity: 0.5,
      }} />
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,0.55) 100%)',
      }} />
      <div style={{
        position: 'absolute', inset: 0,
        background: `repeating-linear-gradient(${seed * 17}deg, transparent 0 ${8 + s(9) * 14}px, rgba(255,255,255,0.04) ${8 + s(9) * 14}px ${10 + s(9) * 14}px)`,
        mixBlendMode: 'screen',
      }} />
      {label && (
        <div style={{
          position: 'absolute', left: 12, bottom: 10,
          fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: 0.5,
          textTransform: 'uppercase', color: 'rgba(255,255,255,0.75)',
        }}>{label}</div>
      )}
    </div>
  );
}

// ── StakeBar (LANDING — labeled, fat) ─────────────────────────────
// Used in the landing page's interactive Stakes demo.
function StakeBar({ back, doubt, height = 36, showLabels = true, compact = false }) {
  const total = back + doubt;
  const pct = total ? (back / total) * 100 : 50;
  const monoStyle = { fontFamily: 'var(--mono)', fontVariantNumeric: 'tabular-nums' };

  return (
    <div style={{ width: '100%' }}>
      {showLabels && (
        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
          fontSize: compact ? 10 : 11, marginBottom: 6, textTransform: 'uppercase',
          letterSpacing: 0.08 + 'em',
        }}>
          <span style={{ color: 'var(--coral)', fontWeight: 600 }}>Back</span>
          <span style={{ color: 'rgba(255,255,255,0.5)', ...monoStyle, fontSize: compact ? 10 : 11 }}>
            {pct.toFixed(0)}% / {(100 - pct).toFixed(0)}%
          </span>
          <span style={{ color: 'rgba(255,255,255,0.85)', fontWeight: 600 }}>Doubt</span>
        </div>
      )}
      <div style={{
        position: 'relative', height, width: '100%',
        background: 'rgba(255,255,255,0.06)',
        border: '1px solid rgba(255,255,255,0.1)',
        borderRadius: height / 2,
        overflow: 'hidden',
        isolation: 'isolate',
      }}>
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: `${pct}%`,
          background: 'var(--coral)',
          transition: 'width 0.4s cubic-bezier(0.2, 0.7, 0.3, 1)',
        }} />
        <div style={{
          position: 'absolute', right: 0, top: 0, bottom: 0,
          width: `${100 - pct}%`,
          background: 'var(--doubt)',
          transition: 'width 0.4s cubic-bezier(0.2, 0.7, 0.3, 1)',
        }} />
        <div style={{
          position: 'absolute', inset: 0, display: 'flex', alignItems: 'center',
          justifyContent: 'space-between', padding: '0 14px',
          fontSize: compact ? 11 : 13, fontWeight: 600,
          ...monoStyle,
        }}>
          <span style={{ color: '#0D0D0D', mixBlendMode: 'screen' }}>{back.toLocaleString()}</span>
          <span style={{ color: '#0D0D0D', mixBlendMode: 'screen' }}>{doubt.toLocaleString()}</span>
        </div>
        <div style={{
          position: 'absolute', left: '50%', top: -2, bottom: -2,
          width: 1, background: 'rgba(255,255,255,0.4)', pointerEvents: 'none',
        }} />
      </div>
    </div>
  );
}

// ── OddsBar (WEB APP — thin, no inline labels) ────────────────────
// Spec: 8px height, rounded, no labels on bar. Coral fill = Back, --doubt = Doubt.
// `you` overlay shows the user's personal stake position as a colored marker.
function OddsBar({ back, doubt, height = 8, you, animate = true }) {
  const total = back + doubt;
  const pct = total ? (back / total) * 100 : 50;
  return (
    <div style={{
      position: 'relative', height, width: '100%',
      borderRadius: height,
      background: 'var(--doubt)',
      overflow: 'hidden',
    }}>
      <div style={{
        position: 'absolute', left: 0, top: 0, bottom: 0,
        width: `${pct}%`,
        background: 'var(--coral)',
        transition: animate ? 'width 0.3s ease' : 'none',
      }} />
      {you && (
        <div style={{
          position: 'absolute', top: -2, bottom: -2,
          left: `calc(${pct}% - 1px)`,
          width: 3,
          background: '#fff',
          boxShadow: '0 0 0 1.5px #0D0D0D',
        }} />
      )}
    </div>
  );
}

// ── StreakRing ─ dashed ring with draw-on stroke animation.
function StreakRing({ day, target = 100, size = 120, stroke = 8, label = 'day streak', showLabel = true, animate = true }) {
  const r = (size - stroke) / 2 - 4;
  const c = 2 * Math.PI * r;
  const pct = Math.min(1, day / target);
  const offset = c * (1 - pct);
  const labelSize = Math.max(9, size * 0.08);
  const numSize = size * 0.28;

  // Draw-on: use a CSS animation keyed by ring circumference.
  const ringStyle = animate ? {
    strokeDasharray: c,
    strokeDashoffset: c,
    animation: 'prove-ring-draw 1.2s ease-out 0.1s forwards',
    '--ring-c': c,
    '--ring-target': offset,
  } : {
    strokeDasharray: `${c * pct} ${c}`,
  };

  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        {/* Dashed faint background ring: 6px dash / 4px gap */}
        <circle cx={size/2} cy={size/2} r={r} fill="none"
          stroke="rgba(255,255,255,0.12)" strokeWidth={stroke}
          strokeDasharray="6 4" />
        {/* Coral progress ring */}
        <circle cx={size/2} cy={size/2} r={r} fill="none"
          stroke="var(--coral)" strokeWidth={stroke}
          strokeLinecap="round"
          transform={`rotate(-90 ${size/2} ${size/2})`}
          style={ringStyle} />
      </svg>
      <div style={{
        position: 'absolute', inset: 0,
        display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center',
        gap: 1,
      }}>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: numSize, fontWeight: 600,
          color: '#fff', letterSpacing: '-0.02em', lineHeight: 1,
          fontVariantNumeric: 'tabular-nums',
        }}>{day}</div>
        {showLabel && size >= 60 && (
          <div style={{
            fontSize: labelSize, letterSpacing: 0.12 + 'em', textTransform: 'uppercase',
            color: 'rgba(255,255,255,0.5)', fontWeight: 500,
          }}>{label}</div>
        )}
      </div>
    </div>
  );
}

// ── Avatar ──
function Avatar({ user, size = 36, ring = false }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%',
      background: user.tone, color: '#0D0D0D',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: 'var(--display)', fontWeight: 700,
      fontSize: size * 0.45, flexShrink: 0,
      boxShadow: ring ? '0 0 0 2px var(--coral), 0 0 0 4px #0D0D0D' : 'none',
    }}>{user.avatar}</div>
  );
}

// ── HabitPill ─ coral pill, lowercase habit label.
function HabitPill({ habit, dark = false, size = 'sm', filled = false }) {
  const compact = size === 'xs';
  const styles = filled ? {
    background: 'var(--coral)',
    color: '#0D0D0D',
    border: '1px solid var(--coral)',
    fontWeight: 700,
  } : {
    background: dark ? 'rgba(255,97,85,0.08)' : 'transparent',
    color: 'var(--coral)',
    border: '1px solid var(--coral)',
    fontWeight: 500,
  };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center',
      padding: compact ? '2px 8px' : '4px 10px',
      fontSize: compact ? 10 : 11,
      letterSpacing: 0.04 + 'em',
      borderRadius: 999,
      textTransform: 'lowercase',
      lineHeight: 1.4,
      ...styles,
    }}>{habit.label}</span>
  );
}

// ── MonoNum ─ JetBrains Mono numeric.
function MonoNum({ children, size = 14, weight = 500, color, tabular = true, style }) {
  return (
    <span style={{
      fontFamily: 'var(--mono)',
      fontSize: size,
      fontWeight: weight,
      color: color || 'inherit',
      fontVariantNumeric: tabular ? 'tabular-nums' : 'normal',
      letterSpacing: '-0.01em',
      ...style,
    }}>{children}</span>
  );
}

// ── PlayOverlay ─ coral play button for video thumbs.
function PlayOverlay({ size = 48 }) {
  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      pointerEvents: 'none',
    }}>
      <div style={{
        width: size, height: size, borderRadius: '50%',
        background: 'var(--coral)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 4px 24px rgba(255,97,85,0.4)',
      }}>
        <svg width={size * 0.36} height={size * 0.36} viewBox="0 0 10 12" fill="#0D0D0D">
          <path d="M0 0 L10 6 L0 12 Z" />
        </svg>
      </div>
    </div>
  );
}

// ── PhoneMock ─ thin device frame for landing-page mockups.
function PhoneMock({ width = 220, height = 460, children, style }) {
  return (
    <div style={{
      width, height, borderRadius: width * 0.13,
      padding: 6,
      background: 'linear-gradient(180deg, #2a2a2a, #0f0f0f)',
      boxShadow: '0 30px 80px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.06) inset',
      position: 'relative', flexShrink: 0,
      ...style,
    }}>
      <div style={{
        width: '100%', height: '100%', borderRadius: width * 0.11,
        background: '#0D0D0D', overflow: 'hidden', position: 'relative',
      }}>
        <div style={{
          position: 'absolute', top: 8, left: '50%', transform: 'translateX(-50%)',
          width: width * 0.28, height: width * 0.05, borderRadius: 999,
          background: '#000', zIndex: 5,
        }} />
        {children}
      </div>
    </div>
  );
}

// ── Marquee ─ horizontally scrolling row, infinite loop.
function Marquee({ children, speed = 40, style }) {
  return (
    <div style={{
      overflow: 'hidden', width: '100%', position: 'relative',
      maskImage: 'linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent)',
      WebkitMaskImage: 'linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent)',
      ...style,
    }}>
      <div style={{
        display: 'inline-flex', whiteSpace: 'nowrap',
        animation: `prove-marquee ${speed}s linear infinite`,
      }}>
        {children}
        {children}
      </div>
    </div>
  );
}

// ── REP Badge ─ shield-shaped, tier-colored.
// Tiers by score: 0–999 Newcomer, 1k–4999 Regular, 5k–9999 Proven, 10k+ Legend
function repTier(score) {
  if (score >= 10000) return { name: 'Legend',   outline: 'var(--coral)', fill: 'var(--coral)', text: '#0D0D0D' };
  if (score >= 5000)  return { name: 'Proven',   outline: 'var(--coral)', fill: 'transparent',  text: 'var(--coral)' };
  if (score >= 1000)  return { name: 'Regular',  outline: 'rgba(255,255,255,0.6)', fill: 'transparent', text: '#fff' };
  return                     { name: 'Newcomer', outline: 'rgba(255,255,255,0.3)', fill: 'transparent', text: 'rgba(255,255,255,0.7)' };
}

function REPBadge({ score, size = 'md', showLabel = true, inline = false }) {
  const tier = repTier(score);
  const sizes = {
    sm: { w: 56,  fs: 11, h: 64 },
    md: { w: 76,  fs: 14, h: 88 },
    lg: { w: 108, fs: 18, h: 124 },
  };
  const dims = sizes[size];
  const formatted = score >= 1000 ? `${(score / 1000).toFixed(score >= 10000 ? 0 : 1)}K` : String(score);

  if (inline) {
    return (
      <span style={{
        display: 'inline-flex', alignItems: 'center', gap: 6,
        padding: '4px 10px',
        border: `1px solid ${tier.outline}`,
        background: tier.fill === 'transparent' ? 'rgba(255,255,255,0.02)' : tier.fill,
        color: tier.text,
        borderRadius: 999,
        fontSize: 11, fontWeight: 700,
        letterSpacing: 0.08 + 'em', textTransform: 'uppercase',
        fontFamily: 'var(--mono)',
      }}>
        <ShieldIcon size={11} stroke={tier.text} fill="none" />
        REP {score.toLocaleString()}
      </span>
    );
  }

  return (
    <div style={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
      <div style={{ position: 'relative', width: dims.w, height: dims.h }}>
        <ShieldIcon size={dims.w} stroke={tier.outline} fill={tier.fill} stroke2 />
        <div style={{
          position: 'absolute', inset: 0,
          display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
          gap: 0,
        }}>
          <MonoNum size={dims.fs + 4} weight={700} color={tier.text} style={{ lineHeight: 1, letterSpacing: '-0.02em' }}>{formatted}</MonoNum>
          <span style={{
            fontSize: 8, fontFamily: 'var(--mono)', letterSpacing: 0.12 + 'em',
            color: tier.text, opacity: 0.7, marginTop: 2,
          }}>REP</span>
        </div>
      </div>
      {showLabel && (
        <span style={{
          fontSize: 10, fontFamily: 'var(--mono)',
          color: 'rgba(255,255,255,0.5)', letterSpacing: 0.1 + 'em', textTransform: 'uppercase',
        }}>{tier.name}</span>
      )}
    </div>
  );
}

function ShieldIcon({ size = 22, stroke = 'var(--coral)', fill = 'none', stroke2 = false }) {
  // Shield path inscribed in a roughly 22×24 viewBox
  const w = size;
  const h = size * (24 / 22);
  return (
    <svg width={w} height={h} viewBox="0 0 22 24" fill="none" style={{ display: 'block' }}>
      <path d="M11 1.5 L20 5 V12 C20 17 16 21.5 11 22.5 C6 21.5 2 17 2 12 V5 Z"
        fill={fill}
        stroke={stroke}
        strokeWidth={stroke2 ? 1.5 : 1.4}
        strokeLinejoin="round"
      />
    </svg>
  );
}

// ── PROVE Window Timer ─ HH:MM:SS countdown with 3 states.
// states: 'open' (>2h), 'closing' (<2h), 'closed'
// `as`: 'banner' (sticky strip with coral left border) | 'compact' (sidebar) | 'inline'
function PROVEWindowTimer({ initialSeconds = 14535, as = 'inline', forceState }) {
  const [s, setS] = useState(initialSeconds);
  useEffect(() => {
    const t = setInterval(() => setS((v) => Math.max(0, v - 1)), 1000);
    return () => clearInterval(t);
  }, []);

  const isClosed = s <= 0 || forceState === 'closed';
  const isClosing = !isClosed && (s < 7200 || forceState === 'closing');

  const h = Math.floor(s / 3600);
  const m = Math.floor((s % 3600) / 60);
  const sec = s % 60;
  const timeStr = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
  const color = isClosed ? 'rgba(255,255,255,0.4)' : isClosing ? 'var(--coral)' : '#fff';
  const labelText = isClosed ? 'opens 6AM tomorrow' : isClosing ? 'closing soon' : 'window open';

  if (as === 'banner') {
    const styles = isClosed ? {
      bg: 'rgba(255,255,255,0.02)',
      bord: '1px solid var(--border)',
      bordLeft: '3px solid rgba(255,255,255,0.15)',
      labelColor: 'var(--text-3)',
      label: 'Window closed',
      dotAnim: 'none',
    } : isClosing ? {
      bg: 'linear-gradient(90deg, rgba(255,97,85,0.15), rgba(255,97,85,0.04))',
      bord: '1px solid rgba(255,97,85,0.3)',
      bordLeft: '3px solid var(--coral)',
      labelColor: 'var(--coral)',
      label: 'Closing soon \u2014 post now',
      dotAnim: 'prove-pulse 1.6s ease-out infinite',
    } : {
      bg: 'linear-gradient(90deg, rgba(255,97,85,0.08), transparent)',
      bord: '1px solid rgba(255,97,85,0.18)',
      bordLeft: '3px solid var(--coral)',
      labelColor: 'var(--coral)',
      label: 'Window open',
      dotAnim: 'prove-pulse 1.6s ease-out infinite',
    };
    return (
      <div style={{
        display: 'flex', alignItems: 'center', gap: 14,
        height: 56, padding: '0 20px',
        background: styles.bg,
        border: styles.bord,
        borderLeft: styles.bordLeft,
        borderRadius: 'var(--radius-card)',
      }}>
        <span style={{
          width: 8, height: 8, borderRadius: '50%',
          background: isClosed ? 'rgba(255,255,255,0.4)' : 'var(--coral)',
          animation: styles.dotAnim,
        }} />
        <span style={{
          fontSize: 11, fontFamily: 'var(--mono)',
          color: styles.labelColor,
          letterSpacing: 0.14 + 'em', textTransform: 'uppercase',
          fontWeight: 700,
        }}>{styles.label}</span>
        <span style={{ width: 1, height: 18, background: 'rgba(255,255,255,0.1)' }} />
        <MonoNum size={isClosing ? 22 : 20} weight={700} color={color} style={{
          letterSpacing: '0.02em',
          animation: isClosing ? 'prove-coral-pulse 1.8s ease-in-out infinite' : 'none',
          textDecoration: isClosed ? 'line-through' : 'none',
        }}>{isClosed ? 'opens 06:00 tomorrow' : timeStr}</MonoNum>
        <a
          onClick={() => { if (!isClosed) window.location.hash = '/post'; }}
          style={{
          marginLeft: 'auto', fontSize: 12,
          color: isClosed ? 'var(--text-3)' : 'var(--coral)',
          fontWeight: 700, cursor: isClosed ? 'default' : 'pointer',
          display: 'inline-flex', alignItems: 'center', gap: 6,
          textTransform: 'uppercase', letterSpacing: 0.06 + 'em',
        }}>
          {isClosed ? 'opens in 06:14:22' : 'Post a proof \u2192'}
        </a>
      </div>
    );
  }

  if (as === 'compact') {
    // Day progress: percent of 24h elapsed.
    const now = new Date();
    const dayPct = (now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()) / 86400 * 100;
    return (
      <div style={{
        background: 'linear-gradient(135deg, rgba(255,97,85,0.12), rgba(255,97,85,0.04))',
        border: '1px solid rgba(255,97,85,0.25)',
        borderRadius: 12,
        padding: 14,
        display: 'flex', flexDirection: 'column', gap: 8,
      }}>
        <div style={{
          fontSize: 9, fontFamily: 'var(--mono)',
          color: 'var(--coral)',
          letterSpacing: 0.14 + 'em', textTransform: 'uppercase',
          fontWeight: 700,
          display: 'flex', alignItems: 'center', gap: 6,
        }}>
          <span style={{
            width: 6, height: 6, borderRadius: '50%',
            background: 'var(--coral)',
            animation: !isClosed ? 'prove-pulse 1.6s ease-out infinite' : 'none',
          }} />
          {isClosed ? 'Window closed' : isClosing ? 'Closing soon' : 'Window open'}
        </div>
        <MonoNum size={26} weight={700} color={color} style={{
          letterSpacing: '-0.01em', lineHeight: 1,
          textDecoration: isClosed ? 'line-through' : 'none',
        }}>{isClosed ? 'opens 06:00' : timeStr}</MonoNum>
        <div style={{
          marginTop: 2, height: 3, width: '100%',
          background: 'rgba(255,255,255,0.08)',
          borderRadius: 2, overflow: 'hidden',
        }}>
          <div style={{
            width: `${dayPct}%`, height: '100%', background: 'var(--coral)',
            transition: 'width 0.5s ease',
          }} />
        </div>
      </div>
    );
  }

  return <MonoNum size={14} weight={600} color={color}>{timeStr}</MonoNum>;
}

// ── NotificationDot ─ unread red/coral dot for nav.
function NotificationDot({ size = 8, style }) {
  return (
    <span style={{
      display: 'inline-block',
      width: size, height: size, borderRadius: '50%',
      background: 'var(--coral)',
      boxShadow: '0 0 0 2px #0D0D0D',
      ...style,
    }} />
  );
}

Object.assign(window, {
  ProveLogo, BlurTile,
  StakeBar, OddsBar,
  StreakRing, Avatar, HabitPill,
  MonoNum, PlayOverlay, PhoneMock, Marquee,
  REPBadge, repTier, ShieldIcon,
  PROVEWindowTimer, NotificationDot,
});
