import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import { GitCommitHorizontal, Zap, CheckCircle2, Clock } from 'lucide-react';
import Card from '../components/ui/Card';
import Tag from '../components/ui/Tag';
import { useApp } from '../store/AppContext';
import * as db from '../lib/db';

// ── Constants ────────────────────────────────────────────────────────────────

const TOTAL_WEEKS = 26;

const BADGE_RULES = [
  { id: 'first_test',    label: 'first-steps',   condition: (u) => u.tests_completed > 0 },
  { id: 'veteran',       label: 'veteran',        condition: (u) => u.tests_completed >= 5 },
  { id: 'perfectionist', label: 'perfectionist',  condition: (u) => u.perfectScores > 0 },
];

// ── Pure helpers ──────────────────────────────────────────────────────────────

/**
 * Streak = consecutive completed weeks counting backwards from the most
 * recent completed week. Does not require knowing the user's personal
 * week number, so it works for every member in one pass.
 */
function computeStreak(heatmap) {
  let last = -1;
  for (let i = TOTAL_WEEKS - 1; i >= 0; i--) {
    if (heatmap[i] !== null) { last = i; break; }
  }
  if (last === -1) return 0;
  let streak = 0;
  for (let i = last; i >= 0; i--) {
    if (heatmap[i] !== null) streak++;
    else break;
  }
  return streak;
}

function timeAgo(dateStr) {
  const diff = Date.now() - new Date(dateStr).getTime();
  const h = Math.floor(diff / 3_600_000);
  if (h < 1) return 'just now';
  if (h < 24) return `${h}h ago`;
  const d = Math.floor(h / 24);
  if (d < 7) return `${d}d ago`;
  return `${Math.floor(d / 7)}w ago`;
}

// ── Sub-components ────────────────────────────────────────────────────────────

const SectionLabel = ({ text }) => (
  <div className="flex items-center gap-3 mb-4">
    <span className="font-mono text-xs text-fg-muted select-none">// {text}</span>
    <div className="flex-1 h-px bg-bg-warm" />
  </div>
);

const Stat = ({ value, label, icon, highlight = false }) => (
  <div className="flex items-center gap-1.5">
    <span className={highlight ? 'text-teal' : 'text-fg-muted'}>{icon}</span>
    <span className={`font-mono text-sm font-bold ${highlight ? 'text-teal' : 'text-fg'}`}>
      {value}
    </span>
    <span className="font-mono text-[10px] text-fg-subtle">{label}</span>
  </div>
);

/**
 * Single heatmap cell. Four intensity levels:
 *   0 = not done (cream)  1 = done  2 = ≥70%  3 = 100% perfect
 */
const HeatCell = ({ score, week }) => {
  const level =
    score === null      ? 0 :
    score === 100       ? 3 :
    score >= 70         ? 2 : 1;

  const bg = [
    'bg-bg-warm',
    'bg-teal/25',
    'bg-teal/55',
    'bg-teal',
  ][level];

  return (
    <div
      title={score === null ? `Week ${week}: not done` : `Week ${week}: ${score}%`}
      className={`w-2.5 h-2.5 rounded-[3px] ${bg} transition-colors duration-300`}
    />
  );
};

const StatusPill = ({ streak, testsCompleted }) => {
  if (testsCompleted === 0)
    return <Tag className="text-[10px] font-mono">○ not started</Tag>;
  if (streak >= 4)
    return <Tag variant="success" className="text-[10px] font-mono">● on a roll 🔥</Tag>;
  if (streak >= 1)
    return <Tag variant="success" className="text-[10px] font-mono">● active</Tag>;
  return <Tag className="text-[10px] font-mono">◌ getting started</Tag>;
};

// ── Main component ────────────────────────────────────────────────────────────

const Leaderboard = () => {
  const { state } = useApp();
  const [users, setUsers]   = useState([]);
  const [feed, setFeed]     = useState([]);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const load = async () => {
      const [leaderboardData, allUsers, allResults, allOnDemand] = await Promise.all([
        db.getLeaderboard(),
        db.getTeamMembers(),
        db.getAllTestResults(),
        db.getAllOnDemandAttempts(),
      ]);

      const nonAdmins    = allUsers.filter(u => u.role !== 'admin');
      const nonAdminIds  = new Set(nonAdmins.map(u => u.id));

      // Group test_results by user_id, keyed by week_number → percentage
      const resultsByUser = {};
      for (const r of allResults) {
        if (!nonAdminIds.has(r.user_id)) continue;
        if (!resultsByUser[r.user_id]) resultsByUser[r.user_id] = {};
        resultsByUser[r.user_id][r.week_number] = r.percentage;
      }

      // Count on-demand perfect scores per user (heatmap stays weekly-only since
      // on-demand attempts have no week_number — they aren't curriculum slots).
      const onDemandPerfectByUser = {};
      for (const r of allOnDemand) {
        if (!nonAdminIds.has(r.user_id)) continue;
        if (r.percentage === 100) {
          onDemandPerfectByUser[r.user_id] = (onDemandPerfectByUser[r.user_id] || 0) + 1;
        }
      }

      // Build enriched user objects
      const enriched = nonAdmins.map(user => {
        const lb      = leaderboardData.find(e => e.user_id === user.id) || {};
        const weekMap = resultsByUser[user.id] || {};

        // 26-element array: index 0 = week 1. null = not done, number = percentage
        const heatmap = Array.from({ length: TOTAL_WEEKS }, (_, i) => {
          const pct = weekMap[i + 1];
          return pct !== undefined ? pct : null;
        });

        const streak       = computeStreak(heatmap);
        const perfectScores = heatmap.filter(s => s === 100).length
                              + (onDemandPerfectByUser[user.id] || 0);

        return {
          id:              user.id,
          name:            user.name,
          points:          lb.points          || 0,
          tests_completed: lb.tests_completed || 0,
          heatmap,
          streak,
          perfectScores,
        };
      });

      // Sort: highest active streak first, then most tests, then name
      enriched.sort((a, b) =>
        b.streak - a.streak ||
        b.tests_completed - a.tests_completed ||
        a.name.localeCompare(b.name)
      );

      // Recent activity feed: merge weekly results and on-demand attempts,
      // newest first, capped at 10.
      const nameMap = Object.fromEntries(allUsers.map(u => [u.id, u.name]));
      const weeklyItems = allResults
        .filter(r => nonAdminIds.has(r.user_id))
        .map(r => ({
          kind:       'weekly',
          key:        `w-${r.user_id}-${r.week_number}`,
          name:       nameMap[r.user_id] || 'Unknown',
          label:      `week-${r.week_number}`,
          score:      r.score,
          total:      r.total,
          percentage: r.percentage,
          created:    r.created,
        }));
      const onDemandItems = allOnDemand
        .filter(r => nonAdminIds.has(r.user_id))
        .map(r => ({
          kind:       'on_demand',
          key:        `od-${r.id}`,
          name:       nameMap[r.user_id] || 'Unknown',
          label:      r.topic_label || 'topic',
          score:      r.score,
          total:      r.total,
          percentage: r.percentage,
          created:    r.created,
        }));
      const recentFeed = [...weeklyItems, ...onDemandItems]
        .sort((a, b) => new Date(b.created) - new Date(a.created))
        .slice(0, 10);

      setUsers(enriched);
      setFeed(recentFeed);
      setLoaded(true);
    };

    load().catch(console.error);
  }, [state.weekNumber]);

  const me     = users.find(u => u.id === state.currentUser?.id);
  const myWeek = state.weekNumber || 0;

  // The user with the longest active streak gets the ★ marker
  const topStreakId = users.find(u => u.streak > 0)?.id;

  return (
    <div className="p-4 md:p-8 max-w-3xl mx-auto pb-24 md:pb-8">

      {/* ── Page header ──────────────────────────────────────────────── */}
      <div className="mb-10">
        <p className="font-mono text-xs text-fg-muted mb-1 select-none">
          // knowledge contributions
        </p>
        <div className="flex items-baseline gap-3 flex-wrap">
          <h1 className="text-2xl md:text-3xl font-bold text-teal">Activity</h1>
          {myWeek > 0 && (
            <span className="font-mono text-xs text-fg-muted bg-bg-warm px-2 py-1 rounded-[var(--r-sm)]">
              branch: week-{myWeek}/26
            </span>
          )}
        </div>
      </div>

      {/* ── Your activity ─────────────────────────────────────────────── */}
      {me && (
        <motion.section
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          className="mb-8"
        >
          <SectionLabel text="your activity" />

          <Card className="border border-bg-warm">
            {/* Name row */}
            <div className="flex items-start justify-between mb-5">
              <div>
                <p className="font-bold text-lg text-teal leading-tight">{me.name}</p>
                <p className="font-mono text-[11px] text-fg-muted">
                  @{me.name.toLowerCase().replace(/\s+/g, '.')}
                </p>
              </div>
              <StatusPill streak={me.streak} testsCompleted={me.tests_completed} />
            </div>

            {/* Heatmap */}
            <div className="mb-5">
              <p className="font-mono text-[9px] text-fg-subtle uppercase tracking-widest mb-2 select-none">
                26-week contributions
              </p>
              <div className="flex flex-wrap gap-[3px]">
                {me.heatmap.map((score, i) => (
                  <HeatCell key={i} score={score} week={i + 1} />
                ))}
              </div>
              {/* Week labels */}
              <div className="flex justify-between mt-1.5">
                <span className="font-mono text-[9px] text-fg-subtle">wk 1</span>
                <span className="font-mono text-[9px] text-fg-subtle">wk 26</span>
              </div>
            </div>

            {/* Stats */}
            <div className="flex gap-5 pt-3 border-t border-bg-warm flex-wrap">
              <Stat
                value={me.points}
                label="commits"
                icon={<GitCommitHorizontal size={12} />}
              />
              <Stat
                value={`${me.streak}w`}
                label="streak"
                icon={<Zap size={12} />}
                highlight={me.streak >= 3}
              />
              <Stat
                value={me.perfectScores}
                label="perfect"
                icon={<CheckCircle2 size={12} />}
                highlight={me.perfectScores > 0}
              />
            </div>
          </Card>
        </motion.section>
      )}

      {/* ── Team contributions ────────────────────────────────────────── */}
      <section className="mb-8">
        <SectionLabel text="team contributions" />

        <Card className="border border-bg-warm p-0 overflow-hidden">
          {loaded && users.length === 0 ? (
            <p className="p-8 text-center font-mono text-sm text-fg-muted">
              $ no contributions yet — start your first week
            </p>
          ) : (
            <div className="divide-y divide-bg-warm">
              {users.map((user, i) => {
                const isMe    = user.id === state.currentUser?.id;
                const badges  = BADGE_RULES.filter(r => r.condition(user));
                const isTop   = user.id === topStreakId;
                const pct     = Math.round((user.tests_completed / TOTAL_WEEKS) * 100);

                return (
                  <motion.div
                    key={user.id}
                    initial={{ opacity: 0, x: -8 }}
                    animate={{ opacity: 1, x: 0 }}
                    transition={{ delay: i * 0.04 }}
                    className={[
                      'px-5 py-4',
                      isMe
                        ? 'bg-teal/5 border-l-4 border-teal'
                        : 'hover:bg-bg-warm/40 transition-colors',
                    ].join(' ')}
                  >
                    {/* Name + meta row */}
                    <div className="flex items-center justify-between mb-2.5 gap-2">
                      <div className="flex items-center gap-1.5 min-w-0">
                        <span className="font-mono text-sm font-medium text-fg truncate">
                          {user.name}
                        </span>
                        {isMe && (
                          <span className="font-mono text-[10px] text-teal/70 flex-shrink-0">
                            (you)
                          </span>
                        )}
                        {isTop && !isMe && (
                          <span
                            title="Longest active streak"
                            className="text-amber-400 text-xs flex-shrink-0"
                          >
                            ★
                          </span>
                        )}
                        {isTop && isMe && (
                          <span
                            title="Longest active streak"
                            className="text-amber-400 text-xs flex-shrink-0"
                          >
                            ★
                          </span>
                        )}
                      </div>

                      <div className="flex items-center gap-3 flex-shrink-0">
                        <span className="font-mono text-[11px] text-fg-muted">
                          {user.tests_completed}/{TOTAL_WEEKS}
                        </span>
                        <span
                          className={`font-mono text-[11px] ${
                            user.streak > 0 ? 'text-teal' : 'text-fg-subtle'
                          }`}
                        >
                          {user.streak > 0 ? `streak: ${user.streak}w` : '─ ─'}
                        </span>
                      </div>
                    </div>

                    {/* Progress bar */}
                    <div className="h-1 bg-bg-warm rounded-full overflow-hidden mb-2.5">
                      <motion.div
                        initial={{ width: 0 }}
                        animate={{ width: `${pct}%` }}
                        transition={{ duration: 0.7, delay: i * 0.04 + 0.1, ease: 'easeOut' }}
                        className={`h-full rounded-full ${isMe ? 'bg-teal' : 'bg-teal/45'}`}
                      />
                    </div>

                    {/* Badges */}
                    {badges.length > 0 && (
                      <div className="flex gap-1.5 flex-wrap">
                        {badges.map(b => (
                          <span
                            key={b.id}
                            className="font-mono text-[10px] bg-teal/10 text-teal px-1.5 py-0.5 rounded"
                          >
                            [{b.label}]
                          </span>
                        ))}
                      </div>
                    )}
                  </motion.div>
                );
              })}
            </div>
          )}
        </Card>
      </section>

      {/* ── Recent activity ───────────────────────────────────────────── */}
      {feed.length > 0 && (
        <section>
          <SectionLabel text="recent activity" />

          <Card className="border border-bg-warm">
            <div className="space-y-2">
              {feed.map((item, i) => (
                <motion.div
                  key={item.key}
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  transition={{ delay: i * 0.03 }}
                  className="flex items-baseline gap-2 font-mono text-xs"
                >
                  <span className="text-teal/40 flex-shrink-0 select-none">›</span>
                  <span className="text-fg font-medium flex-shrink-0">{item.name}</span>
                  <span className="text-fg-subtle">{item.kind === 'on_demand' ? 'tested' : 'completed'}</span>
                  <span className="text-teal font-medium">{item.label}</span>
                  <span className="text-fg-subtle">
                    [{item.score}/{item.total}
                    {item.percentage === 100 && (
                      <span className="text-amber-400"> ★</span>
                    )}
                    ]
                  </span>
                  <span className="ml-auto flex-shrink-0 flex items-center gap-1 text-fg-subtle">
                    <Clock size={10} />
                    {timeAgo(item.created)}
                  </span>
                </motion.div>
              ))}
            </div>
          </Card>
        </section>
      )}

    </div>
  );
};

export default Leaderboard;
