// Shared components: router context, bottom nav, demo banner, toast, modal, count-up, animated checkmark
// Designed for the Gym 24/7 prototype. Dark theme, red accents.

const { useState, useEffect, useRef, createContext, useContext, useMemo, useCallback } = React;

// ─────────────────────────────────────────────────────────────
// Router (string-based, with optional params)
// ─────────────────────────────────────────────────────────────
const RouterCtx = createContext(null);
function useRouter() { return useContext(RouterCtx); }

function RouterProvider({ initial = 'landing', children }) {
  const [route, setRoute] = useState(initial);
  const [params, setParams] = useState({});
  const [hist, setHist] = useState([initial]);

  const go = useCallback((next, p = {}) => {
    setRoute(next);
    setParams(p);
    setHist(h => [...h, next]);
    // scroll the in-frame content back to top
    setTimeout(() => {
      document.querySelectorAll('.phone-screen, .admin-main').forEach(el => { try { el.scrollTop = 0; } catch (_) {} });
    }, 30);
  }, []);

  const back = useCallback(() => {
    setHist(h => {
      if (h.length <= 1) return h;
      const newHist = h.slice(0, -1);
      setRoute(newHist[newHist.length - 1]);
      return newHist;
    });
  }, []);

  return <RouterCtx.Provider value={{ route, params, go, back }}>{children}</RouterCtx.Provider>;
}

// ─────────────────────────────────────────────────────────────
// Toast (global)
// ─────────────────────────────────────────────────────────────
const ToastCtx = createContext(null);
function useToast() { return useContext(ToastCtx); }

function ToastProvider({ children }) {
  const [toast, setToast] = useState(null);
  const show = useCallback((msg, opts = {}) => {
    setToast({ msg, icon: opts.icon || 'check', ts: Date.now() });
    clearTimeout(window.__toastTimer);
    window.__toastTimer = setTimeout(() => setToast(null), opts.duration || 2400);
  }, []);
  return (
    <ToastCtx.Provider value={show}>
      {children}
      {toast && (
        <div className="toast" key={toast.ts}>
          <div style={{ width: 22, height: 22, borderRadius: '50%', background: '#22C55E', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name={toast.icon} size={14} color="#fff" strokeWidth={3} />
          </div>
          <span>{toast.msg}</span>
        </div>
      )}
    </ToastCtx.Provider>
  );
}

// ─────────────────────────────────────────────────────────────
// Demo banner — sticky on top of the device
// ─────────────────────────────────────────────────────────────
function DemoBanner({ hidden, onHide }) {
  if (hidden) return null;
  return (
    <div className="demo-banner">
      <span>Toto je demo. Žiadne reálne dáta sa neukladajú.</span>
      <button onClick={onHide}>✕ skryť</button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Bottom nav (member)
// ─────────────────────────────────────────────────────────────
function BottomNav() {
  const { route, go } = useRouter();
  const items = [
    { id: 'dashboard',    icon: 'home',     label: 'Domov' },
    { id: 'enter',        icon: 'ticket',   label: 'Vstup' },
    { id: 'stats',        icon: 'barchart', label: 'Štatistiky' },
    { id: 'profile',      icon: 'user',     label: 'Profil' },
  ];
  return (
    <div className="bot-nav">
      {items.map(it => {
        const active = route === it.id || (it.id === 'stats' && route === 'achievements');
        return (
          <button key={it.id} className={active ? 'active' : ''} onClick={() => go(it.id)}>
            <span className="nav-dot" />
            <Icon name={it.icon} size={22} color={active ? '#FF1A0F' : '#6B6B6B'} strokeWidth={active ? 2.4 : 2} />
            <span>{it.label}</span>
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Phone top bar (back + title)
// ─────────────────────────────────────────────────────────────
function PhoneTopBar({ title, onBack, trailing }) {
  const { back } = useRouter();
  return (
    <div className="phone-topbar">
      {onBack || back ? (
        <button onClick={onBack || back} style={{
          background: 'rgba(255,255,255,0.06)', border: 'none', color: '#fff',
          width: 36, height: 36, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name="back" size={18} color="#fff" />
        </button>
      ) : <div style={{ width: 36 }} />}
      <div style={{ fontSize: 15, fontWeight: 600, letterSpacing: '-0.005em' }}>{title}</div>
      <div style={{ width: 36, display: 'flex', justifyContent: 'flex-end' }}>{trailing}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Animated count-up number
// ─────────────────────────────────────────────────────────────
function CountUp({ to, duration = 900, className = '', prefix = '', suffix = '' }) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setVal(Math.round(to * eased));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [to, duration]);
  return <span className={'mono ' + className}>{prefix}{val.toLocaleString('sk-SK')}{suffix}</span>;
}

// ─────────────────────────────────────────────────────────────
// Animated check (green) — used in success screens
// ─────────────────────────────────────────────────────────────
function BigCheck({ size = 96, color = '#22C55E', delay = 0 }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%',
      background: `${color}22`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      animation: `fadeIn .35s ease-out ${delay}ms both`,
      position: 'relative',
    }}>
      <div style={{
        position: 'absolute', inset: 0, borderRadius: '50%',
        border: `2px solid ${color}`,
        animation: `wave 1.6s ease-out ${delay + 200}ms infinite`,
      }} />
      <svg width={size * 0.55} height={size * 0.55} viewBox="0 0 24 24" fill="none">
        <path d="M5 12l5 5 9-11" stroke={color} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"
          style={{ strokeDasharray: 80, strokeDashoffset: 80, animation: `drawCheck .5s ease-out ${delay + 200}ms forwards` }}
        />
      </svg>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Modal
// ─────────────────────────────────────────────────────────────
function Modal({ open, onClose, children, maxWidth = 360 }) {
  if (!open) return null;
  return (
    <div className="modal-back" onClick={onClose}>
      <div className="modal" style={{ maxWidth }} onClick={e => e.stopPropagation()}>{children}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Confetti burst (for first achievement)
// ─────────────────────────────────────────────────────────────
function Confetti({ pieces = 30, run = true }) {
  if (!run) return null;
  const cols = ['#E10600', '#FF1A0F', '#FCD34D', '#22C55E', '#fff'];
  const items = useMemo(() => Array.from({ length: pieces }).map((_, i) => ({
    id: i,
    dx: (Math.random() - 0.5) * 240,
    dy: (Math.random() * -240) - 40,
    r:  (Math.random() - 0.5) * 720,
    color: cols[i % cols.length],
    delay: Math.random() * 200,
    size: 6 + Math.random() * 6,
  })), [pieces]);
  return (
    <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'hidden', zIndex: 80 }}>
      {items.map(p => (
        <div key={p.id} style={{
          position: 'absolute', top: '50%', left: '50%',
          width: p.size, height: p.size, background: p.color, borderRadius: 2,
          '--dx': p.dx + 'px', '--dy': p.dy + 'px', '--r': p.r + 'deg',
          animation: `confetti 1.4s cubic-bezier(0.25,0.46,0.45,0.94) ${p.delay}ms forwards`,
        }} />
      ))}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Skeleton (loading)
// ─────────────────────────────────────────────────────────────
function Skeleton({ w = '100%', h = 12, r = 6, style = {} }) {
  return (
    <div style={{
      width: w, height: h, borderRadius: r,
      background: 'linear-gradient(90deg, rgba(255,255,255,0.04), rgba(255,255,255,0.10), rgba(255,255,255,0.04))',
      backgroundSize: '200% 100%', animation: 'shimmer 1.4s linear infinite',
      ...style,
    }} />
  );
}

// inject shimmer keyframe once
if (typeof document !== 'undefined' && !document.getElementById('shim-kf')) {
  const s = document.createElement('style');
  s.id = 'shim-kf';
  s.textContent = '@keyframes shimmer { 0%{background-position:200% 0;} 100%{background-position:-200% 0;} }';
  document.head.appendChild(s);
}

// ─────────────────────────────────────────────────────────────
// Quick segmented (pill) tabs
// ─────────────────────────────────────────────────────────────
function SegTabs({ value, options, onChange, full = true }) {
  return (
    <div style={{
      display: 'flex', padding: 4, gap: 4,
      background: 'rgba(255,255,255,0.04)', border: '1px solid var(--border)',
      borderRadius: 9999, width: full ? '100%' : 'auto',
    }}>
      {options.map(o => {
        const active = o.id === value;
        return (
          <button key={o.id} onClick={() => onChange(o.id)} style={{
            flex: full ? 1 : 'unset',
            background: active ? 'var(--red-primary)' : 'transparent',
            color: active ? '#fff' : 'var(--text-secondary)',
            border: 'none', padding: '8px 14px', borderRadius: 9999,
            fontSize: 13, fontWeight: 600, letterSpacing: '0.01em',
            transition: 'background .15s, color .15s',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
            {o.icon && <Icon name={o.icon} size={14} color="currentColor" strokeWidth={2.2} />}
            {o.label}
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Avatar (initials)
// ─────────────────────────────────────────────────────────────
function Avatar({ initials, size = 36, red = false }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%',
      background: red ? 'var(--red-faded)' : 'var(--bg-tertiary)',
      color: red ? 'var(--red-soft)' : '#fff',
      border: '1px solid var(--border)',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      fontSize: size * 0.36, fontWeight: 600,
      flexShrink: 0,
    }}>{initials}</div>
  );
}

Object.assign(window, {
  RouterProvider, useRouter,
  ToastProvider, useToast,
  DemoBanner, BottomNav, PhoneTopBar,
  CountUp, BigCheck, Modal, Confetti, Skeleton,
  SegTabs, Avatar,
  LiveOccupancyCard, WeekHeatmap,
});

// ─────────────────────────────────────────────────────────────
// Live occupancy widget — "kto je práve teraz vo fitku"
// ─────────────────────────────────────────────────────────────
function LiveOccupancyCard({ compact = false, onClick }) {
  // Drift the current value slightly over time to feel alive
  const [current, setCurrent] = useState(MOCK_LIVE_OCCUPANCY.current);
  const [updatedAgo, setUpdatedAgo] = useState(MOCK_LIVE_OCCUPANCY.updatedSecsAgo);

  useEffect(() => {
    const t = setInterval(() => {
      setCurrent(c => {
        const delta = Math.random() < 0.5 ? -1 : 1;
        const next = c + delta;
        return Math.max(3, Math.min(MOCK_LIVE_OCCUPANCY.capacity, next));
      });
      setUpdatedAgo(0);
    }, 9000);
    const tick = setInterval(() => setUpdatedAgo(s => s + 1), 1000);
    return () => { clearInterval(t); clearInterval(tick); };
  }, []);

  const cap = MOCK_LIVE_OCCUPANCY.capacity;
  const pct = current / cap;
  const status =
    pct < 0.33 ? { label: 'Tichý čas', color: '#22C55E', desc: 'Skvelý čas trénovať.' } :
    pct < 0.66 ? { label: 'Bežne', color: '#F59E0B', desc: 'Stroje sú väčšinou voľné.' } :
    { label: 'Plno', color: 'var(--red-soft)', desc: 'Pripravený si počkať na stroj.' };

  return (
    <div className="card" style={{ padding: compact ? 14 : 18, cursor: onClick ? 'pointer' : 'default' }} onClick={onClick}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 12 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
            <div style={{ width: 7, height: 7, borderRadius: '50%', background: '#22C55E', animation: 'pulse 2s ease-out infinite' }} />
            <div style={{ fontSize: 11, color: 'var(--text-tertiary)', letterSpacing: '0.06em', fontWeight: 600, textTransform: 'uppercase' }}>Práve teraz</div>
          </div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
            <CountUp to={current} duration={500} className="mono" style={{ fontSize: compact ? 32 : 40, fontWeight: 600, letterSpacing: '-0.03em' }} />
            <span style={{ fontSize: 14, color: 'var(--text-secondary)' }} className="mono">/ {cap} ľudí</span>
          </div>
        </div>
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '4px 10px', borderRadius: 9999,
          background: status.color === '#22C55E' ? 'rgba(34,197,94,0.12)' : status.color === '#F59E0B' ? 'rgba(245,158,11,0.12)' : 'var(--red-faded)',
          color: status.color,
          fontSize: 11, fontWeight: 600,
        }}>{status.label}</div>
      </div>

      {/* capacity bar */}
      <div style={{ height: 6, background: 'rgba(255,255,255,0.06)', borderRadius: 3, overflow: 'hidden', marginBottom: 8 }}>
        <div style={{ width: `${pct * 100}%`, height: '100%', background: status.color, transition: 'width .5s ease-out' }} />
      </div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 11, color: 'var(--text-tertiary)' }}>
        <span>{status.desc}</span>
        <span className="mono">aktualizované pred {updatedAgo}s</span>
      </div>

      {!compact && (
        <div style={{ marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--border)' }}>
          <div style={{ fontSize: 11, color: 'var(--text-tertiary)', letterSpacing: '0.06em', fontWeight: 600, textTransform: 'uppercase', marginBottom: 8 }}>Posledných 5 pípaní</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {MOCK_LIVE_OCCUPANCY.recent.map((r, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <Avatar initials={r.initials} size={22} />
                <div style={{ flex: 1, fontSize: 12 }}>{r.name}</div>
                <div style={{
                  fontSize: 10, padding: '2px 6px', borderRadius: 4, fontWeight: 600,
                  background: r.dir === 'in' ? 'rgba(34,197,94,0.12)' : 'rgba(255,255,255,0.06)',
                  color: r.dir === 'in' ? '#22C55E' : 'var(--text-secondary)',
                }}>{r.dir === 'in' ? '↑ prišiel' : '↓ odišiel'}</div>
                <div style={{ fontSize: 10, color: 'var(--text-tertiary)', width: 50, textAlign: 'right' }} className="mono">{r.timeAgo}</div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Week occupancy heatmap — 7 days × 24 hours
// ─────────────────────────────────────────────────────────────
function WeekHeatmap({ data = MOCK_WEEK_HEATMAP, cellSize = 12, gap = 2, highlightNow = true }) {
  const [hover, setHover] = useState(null);

  // Find global max for color scaling
  const max = Math.max(...data.flatMap(d => d.hours));
  // Current day/hour to highlight
  const now = new Date();
  const todayIdx = (now.getDay() + 6) % 7; // 0 = Mon
  const nowHour = now.getHours();

  // Find quietest hour today + busiest hour today for callouts
  const today = data[todayIdx];
  const busiestHour = today.hours.indexOf(Math.max(...today.hours));
  const quietHours = today.hours
    .map((v, h) => ({ v, h }))
    .filter(({ h }) => h >= 5 && h <= 23)
    .sort((a, b) => a.v - b.v);
  const bestNow = quietHours[0];

  const colorFor = (v) => {
    if (v === 0) return 'var(--bg-tertiary)';
    const t = v / max;
    if (t < 0.20) return 'rgba(225,6,0,0.15)';
    if (t < 0.45) return 'rgba(225,6,0,0.35)';
    if (t < 0.70) return 'rgba(225,6,0,0.60)';
    return 'var(--red-primary)';
  };

  return (
    <div>
      {/* hour ruler */}
      <div style={{ display: 'flex', gap, marginLeft: 26, marginBottom: 4 }}>
        {Array.from({ length: 24 }).map((_, h) => (
          <div key={h} style={{
            width: cellSize, flexShrink: 0,
            textAlign: 'center', fontSize: 8, color: 'var(--text-tertiary)',
            visibility: (h % 6 === 0 || h === 23) ? 'visible' : 'hidden',
          }} className="mono">{h.toString().padStart(2, '0')}</div>
        ))}
      </div>

      {data.map((day, di) => (
        <div key={di} style={{ display: 'flex', alignItems: 'center', gap, marginBottom: gap }}>
          <div style={{ width: 22, fontSize: 10, color: di === todayIdx && highlightNow ? 'var(--red-soft)' : 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '0.04em', fontWeight: di === todayIdx && highlightNow ? 700 : 500 }} className="mono">{day.day}</div>
          {day.hours.map((v, h) => {
            const isNow = highlightNow && di === todayIdx && h === nowHour;
            return (
              <div key={h}
                onMouseEnter={() => setHover({ day: day.day, hour: h, v })}
                onMouseLeave={() => setHover(null)}
                style={{
                  width: cellSize, height: cellSize, borderRadius: 2,
                  background: colorFor(v),
                  boxShadow: isNow ? '0 0 0 1.5px #fff' : 'none',
                  transition: 'transform .12s',
                  cursor: 'pointer',
                  flexShrink: 0,
                }}
              />
            );
          })}
        </div>
      ))}

      {/* legend + tooltip */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 12 }}>
        <div style={{ fontSize: 11, color: 'var(--text-secondary)', minHeight: 16 }}>
          {hover
            ? <>~<b style={{ color: '#fff' }} className="mono">{hover.v}</b> ľudí · {hover.day} · {hover.hour.toString().padStart(2,'0')}:00</>
            : 'Klikni / podrž na bunke pre detaily.'}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 10, color: 'var(--text-tertiary)' }}>
          <span>menej</span>
          {[0, 0.2, 0.45, 0.70, 1].map((t, i) => (
            <div key={i} style={{ width: 10, height: 10, borderRadius: 2, background: colorFor(t * max) }} />
          ))}
          <span>viac</span>
        </div>
      </div>

      {/* "best time today" recommendation */}
      {highlightNow && bestNow && (
        <div style={{ marginTop: 14, padding: '10px 12px', background: 'rgba(34,197,94,0.08)', border: '1px solid rgba(34,197,94,0.25)', borderRadius: 8, display: 'flex', alignItems: 'center', gap: 10 }}>
          <Icon name="clock" size={18} color="#22C55E" />
          <div style={{ fontSize: 12, lineHeight: 1.4 }}>
            Dnes je najmenej ľudí o <b className="mono" style={{ color: '#22C55E' }}>{bestNow.h.toString().padStart(2,'0')}:00</b>
            {' '}— priemer <b className="mono">{bestNow.v}</b> ľudí. Najviac okolo <b className="mono">{busiestHour.toString().padStart(2,'0')}:00</b>.
          </div>
        </div>
      )}
    </div>
  );
}
