import { useEffect, useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import ProfileDropdown from '../components/ProfileDropdown';

const API = import.meta.env.VITE_API_URL;

const GRADES = [
  { id: 'G3', label: 'Grade 3' },
  { id: 'G6', label: 'Grade 6' },
  { id: 'G9', label: 'Grade 9' },
];

const LB_SLOTS = 10;

const TIERS = [
  { name: 'Bronze',   min: 800,  max: 899,      color: '#cd7f32', glow: 'rgba(205,127,50,0.45)',  next: 900  },
  { name: 'Silver',   min: 900,  max: 1099,     color: '#b0bec5', glow: 'rgba(176,190,197,0.45)', next: 1100 },
  { name: 'Gold',     min: 1100, max: 1299,     color: '#f5c518', glow: 'rgba(245,197,24,0.55)',  next: 1300 },
  { name: 'Platinum', min: 1300, max: 1499,     color: '#90caf9', glow: 'rgba(144,202,249,0.5)',  next: 1500 },
  { name: 'Diamond',  min: 1500, max: Infinity, color: '#64ffda', glow: 'rgba(100,255,218,0.55)', next: null },
];

function getTier(elo) {
  return TIERS.find(t => elo >= t.min && elo <= t.max) ?? TIERS[0];
}

const RANK_STYLES = [
  { color: '#f5c518', textShadow: '0 0 12px rgba(245,197,24,0.6)' },
  { color: '#c0ccda', textShadow: '0 0 10px rgba(192,204,218,0.4)' },
  { color: '#e0915a', textShadow: '0 0 10px rgba(224,145,90,0.4)' },
];

function decodeJwt(token) {
  try { return JSON.parse(atob(token.split('.')[1])); }
  catch { return null; }
}

function fmtTime(ms) {
  if (ms == null) return '—';
  const s = Math.floor(ms / 1000);
  return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
}

function fmtRelative(dateStr) {
  const diff = Date.now() - new Date(dateStr).getTime();
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return 'just now';
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  return `${Math.floor(hrs / 24)}d ago`;
}

function getGreeting() {
  const h = new Date().getHours();
  if (h < 5)  return 'Night owl mode';
  if (h < 12) return 'Good morning';
  if (h < 17) return 'Good afternoon';
  return 'Good evening';
}

function useCountUp(target, duration = 900, enabled = true) {
  const [value, setValue] = useState(0);
  const rafRef = useRef(null);

  useEffect(() => {
    if (!enabled || target == null || target === 0) {
      setValue(target ?? 0);
      return;
    }
    const start = Date.now();
    const tick = () => {
      const elapsed = Date.now() - start;
      const progress = Math.min(elapsed / duration, 1);
      const eased = 1 - Math.pow(1 - progress, 3);
      setValue(Math.round(eased * target));
      if (progress < 1) rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [target, duration, enabled]);

  return value;
}

function TierBadge({ elo, size = 'md' }) {
  const tier = getTier(elo);
  const isLg = size === 'lg';
  return (
    <span
      className="tier-badge"
      style={{
        '--tier-color': tier.color,
        '--tier-glow': tier.glow,
        fontSize: isLg ? 12 : 10,
        padding: isLg ? '4px 12px' : '3px 9px',
      }}
    >
      {tier.name}
    </span>
  );
}

function TierProgress({ elo }) {
  const tier = getTier(elo);
  if (!tier.next) return null;
  const pct = Math.round(((elo - tier.min) / (tier.next - tier.min)) * 100);
  const nextTier = TIERS.find(t => t.min === tier.next);
  return (
    <div className="tier-progress">
      <div className="tier-progress__labels">
        <span style={{ color: tier.color }}>{tier.name}</span>
        <span className="tier-progress__pct">{pct}%</span>
        <span style={{ color: nextTier?.color ?? tier.color }}>{nextTier?.name}</span>
      </div>
      <div className="tier-progress__bar">
        <div
          className="tier-progress__fill"
          style={{ width: `${pct}%`, background: tier.color, boxShadow: `0 0 8px ${tier.glow}` }}
        />
      </div>
    </div>
  );
}

function LeaderboardTable({ entries, loading, highlightRank, tab }) {
  if (loading) {
    return (
      <div style={{ padding: '12px 16px', display: 'flex', flexDirection: 'column', gap: 8 }}>
        {[...Array(LB_SLOTS)].map((_, i) => (
          <div key={i} className="skel-pill" style={{ height: 44, animationDelay: `${i * 0.06}s` }} />
        ))}
      </div>
    );
  }

  const padded = [
    ...entries,
    ...[...Array(Math.max(0, LB_SLOTS - entries.length))].map((_, i) => ({
      rank: entries.length + i + 1,
      ghost: true,
    })),
  ];

  return (
    <div className="lb-table">
      <div className="lb-header">
        <span className="lb-header__rank">#</span>
        <span className="lb-header__player">Player</span>
        <span className="lb-header__time">{tab === 'elo' ? 'ELO' : 'Best Time'}</span>
      </div>
      {padded.map((entry, idx) => {
        const rowAnim = { animation: 'rowFadeUp 0.3s ease-out both', animationDelay: `${idx * 40}ms` };
        if (entry.ghost) {
          return (
            <div key={`g${entry.rank}`} className="lb-row lb-row--ghost" style={rowAnim}>
              <span className="lb-rank lb-rank--num">{entry.rank}</span>
              <div className="lb-user">
                <div className="lb-avatar lb-avatar--ghost" />
                <span className="lb-ghost-bar" />
              </div>
              <span className="lb-ghost-time">{tab === 'elo' ? '—' : '—:——'}</span>
            </div>
          );
        }
        const isCurrent = highlightRank !== null && entry.rank === highlightRank;
        const rankStyle = entry.rank <= 3 ? RANK_STYLES[entry.rank - 1] : null;
        const playerLabel = entry.username ? `@${entry.username}` : entry.displayName;
        const fallbackLetter = (entry.username ?? entry.displayName)?.[0]?.toUpperCase() ?? '?';
        return (
          <div key={entry.rank} className={`lb-row${isCurrent ? ' lb-row--current' : ''}`} style={rowAnim}>
            <span className={`lb-rank${entry.rank > 3 ? ' lb-rank--num' : ''}`} style={rankStyle ?? undefined}>
              {entry.rank}
            </span>
            <div className="lb-user">
              {entry.avatarUrl
                ? <img className="lb-avatar" src={entry.avatarUrl} alt={playerLabel} referrerPolicy="no-referrer" />
                : <div className="lb-avatar lb-avatar--fallback">{fallbackLetter}</div>
              }
              <span className="lb-name">{playerLabel}</span>
              {isCurrent && <span className="lb-you">YOU</span>}
            </div>
            <span className="lb-score lb-score--time">
              {tab === 'elo' ? (entry.elo?.toLocaleString() ?? '—') : fmtTime(entry.bestTime)}
            </span>
          </div>
        );
      })}
    </div>
  );
}

function MatchHistory({ matches, loading }) {
  if (loading) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: '12px 16px' }}>
        {[0, 1, 2].map(i => (
          <div key={i} className="skel-pill" style={{ height: 60, animationDelay: `${i * 0.07}s` }} />
        ))}
      </div>
    );
  }
  if (!matches.length) {
    return (
      <div className="dash-empty">
        <div className="dash-empty__icon">🕐</div>
        <span className="dash-empty__text">No games played yet</span>
        <span className="dash-empty__sub">Queue up to start climbing</span>
      </div>
    );
  }
  return (
    <div className="match-history">
      {matches.slice(0, 5).map((m, i) => {
        const sign = m.eloChange >= 0 ? '+' : '';
        const eloDeltaColor = m.eloChange >= 0 ? '#1b8a2d' : '#c62828';
        return (
          <div key={m.id ?? i} className={`match-row${m.won ? ' match-row--win' : ' match-row--loss'}`}>
            {/* Win/loss emoji icon */}
            <div
              className={`match-chip${m.won ? ' match-chip--win' : ' match-chip--loss'}`}
              style={{ fontSize: 20, display: 'flex', alignItems: 'center', justifyContent: 'center' }}
            >
              {m.won ? '🏆' : '💀'}
            </div>

            {/* Center: grade badge · label · ELO delta · time · ago */}
            <div className="match-info" style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 3 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 7, flexWrap: 'wrap' }}>
                <span style={{
                  fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 4,
                  background: '#f0f4ff', color: '#1a73e8',
                  letterSpacing: '0.04em', fontFamily: 'system-ui,sans-serif',
                }}>
                  {m.grade}
                </span>
                <span style={{
                  fontSize: 14, fontWeight: 700,
                  color: m.won ? '#1b8a2d' : '#c62828',
                  fontFamily: 'system-ui,sans-serif',
                }}>
                  {m.won ? 'Victory' : 'Defeat'}
                </span>
                <span style={{
                  fontSize: 13, fontWeight: 700, color: eloDeltaColor,
                  fontFamily: 'system-ui,sans-serif',
                }}>
                  {sign}{m.eloChange} ELO
                </span>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span className="match-ago">{fmtRelative(m.playedAt)}</span>
              </div>
            </div>

            {/* Right: ELO after */}
            <span className="match-elo-after" style={{ whiteSpace: 'nowrap' }}>
              {m.eloAfter?.toLocaleString()} ELO
            </span>
          </div>
        );
      })}
    </div>
  );
}

function LoadingSkeleton() {
  return (
    <>
      <div className="arena-bg"><div className="arena-grain" /></div>
      <nav className="dash-nav">
        <div className="skel-pill" style={{ width: 140, height: 22 }} />
        <div className="skel-pill" style={{ width: 40, height: 40, borderRadius: '50%' }} />
      </nav>
      <main className="page dash-page">
        <div className="db-wrap">
          <div className="skel-pill" style={{ width: 280, height: 72, marginBottom: 24, alignSelf: 'center' }} />
          <div className="skel-pill" style={{ width: 240, height: 40, borderRadius: 999, marginBottom: 40, alignSelf: 'center' }} />
          <div className="skel-pill" style={{ height: 60, marginBottom: 28 }} />
          <div className="db-stats">
            {[0,1,2,3].map(i => <div key={i} className="skel-pill" style={{ height: 88, animationDelay: `${i*0.07}s` }} />)}
          </div>
          <div className="skel-pill" style={{ height: 480 }} />
        </div>
      </main>
    </>
  );
}

export default function Dashboard() {
  const navigate = useNavigate();
  const [token,         setToken]         = useState(null);
  const [jwtPayload,    setJwtPayload]    = useState(null);
  const [user,          setUser]          = useState(null);
  const [username,      setUsername]      = useState(null);
  const [stats,         setStats]         = useState([]);
  const [leaderboard,   setLeaderboard]   = useState([]);
  const [matches,       setMatches]       = useState([]);
  const [selectedGrade, setSelectedGrade] = useState('G3');
  const [lbTab,         setLbTab]         = useState('elo');
  const [loading,       setLoading]       = useState(true);
  const [lbLoading,     setLbLoading]     = useState(false);
  const [matchLoading,  setMatchLoading]  = useState(false);
  const [error,         setError]         = useState(null);
  const [statsReady,    setStatsReady]    = useState(false);
  const [bouncingGrade, setBouncingGrade] = useState(null);
  const [onlineCount,   setOnlineCount]   = useState(null);

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const urlToken = params.get('token');
    let tok = urlToken;
    if (urlToken) {
      sessionStorage.setItem('ranked_token', urlToken);
      history.replaceState(null, '', window.location.pathname);
    } else {
      tok = sessionStorage.getItem('ranked_token');
    }
    if (!tok) { navigate('/'); return; }
    setToken(tok);
    setJwtPayload(decodeJwt(tok));
  }, [navigate]);

  useEffect(() => {
    if (!token) return;
    const headers = { Authorization: `Bearer ${token}` };
    Promise.all([fetch(`${API}/auth/me`, { headers }), fetch(`${API}/me/stats`, { headers })])
      .then(async ([meRes, statsRes]) => {
        if (meRes.status === 401) { sessionStorage.removeItem('ranked_token'); navigate('/'); return; }
        const [meData, statsData] = await Promise.all([meRes.json(), statsRes.json()]);
        setUser(meData);
        setUsername(meData.username ?? null);
        setStats(statsData.entries ?? []);
        setLoading(false);
        requestAnimationFrame(() => setStatsReady(true));
      })
      .catch(() => { setError('Could not reach the server.'); setLoading(false); });
  }, [token, navigate]);

  useEffect(() => {
    if (!token) return;
    setLbLoading(true);
    fetch(`${API}/leaderboard?grade=${selectedGrade}&type=${lbTab}`)
      .then(r => r.json())
      .then(d => setLeaderboard(Array.isArray(d) ? d : []))
      .catch(() => setLeaderboard([]))
      .finally(() => setLbLoading(false));
  }, [token, selectedGrade, lbTab]);

  useEffect(() => {
    if (!token) return;
    setMatchLoading(true);
    fetch(`${API}/me/recent-matches?grade=${selectedGrade}`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then(r => r.json())
      .then(d => setMatches(Array.isArray(d) ? d : []))
      .catch(() => setMatches([]))
      .finally(() => setMatchLoading(false));
  }, [token, selectedGrade]);

  useEffect(() => {
    const fetchOnline = () => {
      fetch(`${API}/online-count`)
        .then(r => r.json())
        .then(d => setOnlineCount(d.online ?? 0))
        .catch(() => {});
    };
    fetchOnline();
    const id = setInterval(fetchOnline, 30000);
    return () => clearInterval(id);
  }, []);

  const signOut = () => { sessionStorage.removeItem('ranked_token'); navigate('/'); };

  const currentEntry  = stats.find(e => e.grade === selectedGrade);
  const highlightRank = lbTab === 'elo' ? (currentEntry?.eloRank ?? null) : (currentEntry?.timeRank ?? null);
  const displayName   = user?.displayName ?? jwtPayload?.name ?? 'Player';
  const firstName     = displayName.split(' ')[0];
  const avatarUrl     = user?.avatarUrl ?? jwtPayload?.picture ?? null;
  const initial       = displayName[0]?.toUpperCase() ?? '?';
  const elo           = currentEntry?.elo ?? 800;
  const tier          = getTier(elo);
  const winStreak     = currentEntry?.winStreak ?? 0;
  const eloRank       = currentEntry?.eloRank ?? null;
  const totalPlayers  = currentEntry?.totalPlayers ?? 0;
  const gamesPlayed   = currentEntry?.gamesPlayed ?? 0;

  const topPct = eloRank && totalPlayers > 0
    ? Math.max(1, Math.round((eloRank / totalPlayers) * 100))
    : null;

  const animatedElo = useCountUp(elo, 1000, statsReady);
  const animatedGames = useCountUp(gamesPlayed, 800, statsReady);

  if (loading) return <LoadingSkeleton />;

  const heroLabel = username ?? firstName;

  const casualLabel = gamesPlayed === 0 ? 'Play First Game' : 'Casual';

  return (
    <>
      <div className="arena-bg"><div className="arena-grain" /></div>

      <nav className="dash-nav">
        <span className="dash-nav__logo">RANKED<span>EQAO</span></span>
        <div className="dash-nav__right">
          <ProfileDropdown displayName={displayName} avatarUrl={avatarUrl} initial={initial} onSignOut={signOut} />
        </div>
      </nav>

      <main className="page dash-page">
        <div className="db-wrap">

          {error && (
            <div className="dash-error-banner" style={{ maxWidth: '100%', marginBottom: 24 }}>
              <span>{error}</span>
              <button className="dash-error-banner__dismiss" onClick={() => setError(null)}>✕</button>
            </div>
          )}

          {/* ── Hero ── */}
          <section className="db-hero">
            <p className="db-greeting">{getGreeting()},</p>
            <div className="db-hero__namerow">
              <h1 className="db-hero__name">{heroLabel}</h1>
              <TierBadge elo={elo} size="lg" />
            </div>

            {winStreak >= 2 && (
              <div className="win-streak">
                <span className="win-streak__fire">🔥</span>
                <span className="win-streak__label">{winStreak} win streak</span>
              </div>
            )}

            {topPct && (
              <p className="db-top-pct">
                Top <strong>{topPct}%</strong> in Grade {selectedGrade.replace('G', '')}
              </p>
            )}

            <div className="dash-grade-tabs" style={{ marginTop: 20 }}>
              {GRADES.map(g => (
                <button
                  key={g.id}
                  className={`dash-grade-tab${selectedGrade === g.id ? ' dash-grade-tab--active' : ''}`}
                  style={bouncingGrade === g.id ? { animation: 'gradeTabBounce 0.2s ease-out' } : {}}
                  onClick={() => {
                    setSelectedGrade(g.id);
                    setBouncingGrade(g.id);
                    setTimeout(() => setBouncingGrade(null), 200);
                  }}
                >
                  {g.label}
                </button>
              ))}
            </div>
          </section>

          {/* ── CTA buttons ── */}
          <div className="db-cta">
            <button className="db-btn db-btn--gold" onClick={() => navigate('/game', { state: { grade: selectedGrade } })}>
              {casualLabel}
            </button>
            <button className="db-btn db-btn--blue" onClick={() => navigate('/queue', { state: { grade: selectedGrade } })}>
              Queue Ranked
            </button>
          </div>

          {/* ── Online count ── */}
          {onlineCount !== null && (
            <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 8 }}>
              <span style={{
                fontSize: 12, fontWeight: 600, color: 'rgba(255,255,255,0.5)',
                display: 'flex', alignItems: 'center', gap: 6,
                fontFamily: 'system-ui, sans-serif',
              }}>
                <span style={{
                  width: 7, height: 7, borderRadius: '50%',
                  background: '#4caf50',
                  boxShadow: '0 0 6px rgba(76,175,80,0.8)',
                  display: 'inline-block',
                }} />
                {onlineCount} {onlineCount === 1 ? 'player' : 'players'} online
              </span>
            </div>
          )}

          {/* ── ELO + Tier progress ── */}
          <div className="db-elo-block">
            <div className="db-elo-block__inner">
              <div className="db-elo-main">
                <span className="db-elo-val" style={{ color: tier.color, textShadow: `0 0 24px ${tier.glow}` }}>
                  {animatedElo.toLocaleString()}
                </span>
                <span className="db-elo-label">ELO</span>
                {eloRank && (
                  <span className="db-elo-rank">
                    #{eloRank}
                    {totalPlayers > 0 && <span className="db-elo-rank__total"> / {totalPlayers}</span>}
                  </span>
                )}
              </div>
              <div className="db-elo-block__right">
                <TierProgress elo={elo} />
              </div>
            </div>
          </div>

          {/* ── Stats strip ── */}
          <div className="db-stats">
            {[
              { label: 'Best Time', value: fmtTime(currentEntry?.bestTime), accent: true },
              { label: 'Games',     value: animatedGames },
              { label: 'Correct',  value: currentEntry?.totalCorrect ?? 0 },
              { label: 'Time Rank', value: currentEntry?.timeRank != null ? `#${currentEntry.timeRank}` : '—' },
            ].map(s => (
              <div key={s.label} className="db-stat">
                <span className="db-stat__val" style={s.accent ? { color: 'var(--gold)', textShadow: '0 0 18px rgba(245,197,24,0.35)' } : {}}>
                  {s.value}
                </span>
                <span className="db-stat__label">{s.label}</span>
              </div>
            ))}
          </div>

          {/* ── Recent Matches + Leaderboard side by side ── */}
          <div className="db-two-col">

            {/* Recent Matches */}
            <section className="db-section db-section--half">
              <div className="db-section__hd">
                <span className="db-section__title">Recent Matches</span>
                {winStreak >= 2 && (
                  <span className="db-section__badge" style={{ background: 'rgba(245,197,24,0.08)', borderColor: 'rgba(245,197,24,0.3)', color: 'var(--gold)' }}>
                    🔥 {winStreak} streak
                  </span>
                )}
              </div>
              <div className="dash-card">
                <MatchHistory matches={matches} loading={matchLoading} />
              </div>
            </section>

            {/* Leaderboard */}
            <section className="db-section db-section--half">
              <div className="db-section__hd">
                <span className="db-section__title">Leaderboard</span>
                <div className="lb-tabs">
                  <button className={`lb-tab${lbTab === 'elo'  ? ' lb-tab--active' : ''}`} onClick={() => setLbTab('elo')}>ELO</button>
                  <button className={`lb-tab${lbTab === 'time' ? ' lb-tab--active' : ''}`} onClick={() => setLbTab('time')}>Time</button>
                </div>
              </div>
              <div className="dash-card">
                <LeaderboardTable entries={leaderboard} loading={lbLoading} highlightRank={highlightRank} tab={lbTab} />
              </div>
            </section>

          </div>

          {/* ── All-grades overview ── */}
          <section className="db-section">
            <div className="db-section__hd">
              <span className="db-section__title">All Grades</span>
            </div>
            <div className="db-grades">
              {GRADES.map(g => {
                const e = stats.find(s => s.grade === g.id);
                const t = getTier(e?.elo ?? 800);
                return (
                  <div
                    key={g.id}
                    className={`db-grade-cell${selectedGrade === g.id ? ' db-grade-cell--active' : ''}`}
                    onClick={() => setSelectedGrade(g.id)}
                  >
                    <div className="db-grade-cell__top">
                      <span className="db-grade-cell__name">{g.label}</span>
                      <span className="tier-badge tier-badge--sm" style={{ '--tier-color': t.color, '--tier-glow': t.glow }}>
                        {t.name}
                      </span>
                    </div>
                    <div className="db-grade-cell__row">
                      <span className="db-grade-cell__val db-grade-cell__val--elo" style={{ color: t.color, textShadow: `0 0 10px ${t.glow}` }}>
                        {e?.elo?.toLocaleString() ?? '800'}
                      </span>
                      <span className="db-grade-cell__unit">ELO</span>
                    </div>
                    <div className="db-grade-cell__row">
                      <span className="db-grade-cell__val">{fmtTime(e?.bestTime)}</span>
                      <span className="db-grade-cell__unit">best</span>
                    </div>
                    <div className="db-grade-cell__row">
                      <span className="db-grade-cell__val">{e?.gamesPlayed ?? 0}</span>
                      <span className="db-grade-cell__unit">games</span>
                    </div>
                  </div>
                );
              })}
            </div>
          </section>

        </div>
      </main>
    </>
  );
}
