import React, { useState, useEffect } from 'react';
import { Player, PointsBreakdown } from '../types';
import { motion, AnimatePresence, useSpring, useTransform, LayoutGroup } from 'framer-motion';
import { Loader2, Flame, Rocket, Zap, X, Crown, Medal, Trophy } from 'lucide-react';
import { PlayerAvatar, getAvatarColors } from './PlayerAvatar';

const AnimatedNumber: React.FC<{ value: number; duration?: number }> = ({ value, duration = 600 }) => {
  const spring = useSpring(0, { duration });
  const display = useTransform(spring, (latest) => Math.round(latest));
  const [displayValue, setDisplayValue] = useState(0);

  useEffect(() => {
    spring.set(value);
    const unsubscribe = display.on('change', (v) => setDisplayValue(v));
    return () => unsubscribe();
  }, [value, spring, display]);

  return <span>{displayValue}</span>;
};

interface BonusBadgeProps {
  points: number;
  label: string;
  icon: React.ReactNode;
  color: string;
  delay: number;
}

const BonusBadge: React.FC<BonusBadgeProps> = ({ points, label, icon, color, delay }) => (
  <motion.div
    initial={{ scale: 0, opacity: 0 }}
    animate={{ scale: 1, opacity: 1 }}
    transition={{ delay, type: 'spring', stiffness: 500, damping: 15 }}
    className={`flex items-center gap-1 px-2 py-1 rounded-full text-white font-bold text-sm ${color}`}
  >
    {icon}
    <span>+{points}</span>
    <span className="text-white/80">{label}</span>
  </motion.div>
);

const PenaltyBadge: React.FC<{ points: number; delay: number }> = ({ points, delay }) => (
  <motion.div
    initial={{ scale: 0, opacity: 0 }}
    animate={{ scale: 1, opacity: 1 }}
    transition={{ delay, type: 'spring', stiffness: 500, damping: 15 }}
    className="flex items-center gap-1 px-2 py-1 rounded-full bg-red-500 text-white font-bold text-sm"
  >
    <X size={14} />
    <span>-{points}</span>
  </motion.div>
);

interface PlayerRowProps {
  player: Player & { displayName: string };
  maxScore: number;
  rank: number;
  currentScore: number;
  phase: number;
  baseDelay: number;
}

const PlayerRow: React.FC<PlayerRowProps> = ({ player, maxScore, rank, currentScore, phase, baseDelay }) => {
  const breakdown = player.pointsBreakdown;
  
  const barWidth = maxScore > 0 ? (currentScore / maxScore) * 100 : 0;

  const isFirst = rank === 1;
  const isSecond = rank === 2;
  const isThird = rank === 3;
  const isTop3 = rank <= 3;

  let rankStyles = "bg-white border-gray-100";
  let rankBadgeStyles = "bg-gray-100 text-gray-500";
  
  if (isFirst) {
    rankStyles = "bg-gradient-to-r from-yellow-50 to-amber-100 border-amber-300 shadow-lg scale-[1.02] z-10";
    rankBadgeStyles = "bg-gradient-to-br from-yellow-400 to-amber-600 text-white shadow-sm";
  } else if (isSecond) {
    rankStyles = "bg-gradient-to-r from-gray-50 to-slate-100 border-slate-300 shadow-md z-0";
    rankBadgeStyles = "bg-gradient-to-br from-slate-300 to-slate-500 text-white shadow-sm";
  } else if (isThird) {
    rankStyles = "bg-gradient-to-r from-orange-50 to-orange-100 border-orange-200 shadow-md z-0";
    rankBadgeStyles = "bg-gradient-to-br from-orange-300 to-orange-500 text-white shadow-sm";
  }

  return (
    <motion.div
      layout
      layoutId={player.id}
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ 
        layout: { type: "spring", stiffness: 300, damping: 30 },
        opacity: { duration: 0.3 } 
      }}
      className={`flex items-center gap-3 md:gap-4 p-3 md:p-4 rounded-xl md:rounded-2xl border-2 ${rankStyles}`}
    >
      <div className={`flex items-center justify-center w-8 h-8 md:w-10 md:h-10 rounded-full font-black text-lg md:text-xl shrink-0 ${rankBadgeStyles}`}>
        {rank}
      </div>

      <div className="flex-1 min-w-0 flex flex-col gap-2">
        <div className="flex items-center justify-between gap-3 w-full">
          <div className="flex items-center gap-3 min-w-0">
            <div className="relative">
              <PlayerAvatar seed={player.avatarSeed} size={isTop3 ? 40 : 32} />
              {isFirst && (
                <motion.div 
                  initial={{ scale: 0, rotate: -45 }}
                  animate={{ scale: 1, rotate: -15 }}
                  transition={{ delay: 0.5, type: 'spring' }}
                  className="absolute -top-3 -left-2 drop-shadow-md"
                >
                  <Crown size={24} className="fill-yellow-400 text-yellow-600" />
                </motion.div>
              )}
            </div>
            <span className={`font-black font-display truncate ${isTop3 ? 'text-xl' : 'text-lg'}`}>
              {player.displayName}
            </span>
          </div>
          <span className={`font-black font-display ${isTop3 ? 'text-3xl text-theme-primary' : 'text-2xl text-gray-700'}`}>
            <AnimatedNumber value={currentScore} />
          </span>
        </div>

        <div className="w-full h-8 md:h-10 bg-black/5 rounded-full overflow-hidden relative">
          <motion.div
            className="h-full rounded-full"
            style={{ background: `linear-gradient(90deg, ${getAvatarColors(player.avatarSeed)[0]}, ${getAvatarColors(player.avatarSeed)[1]})` }}
            initial={{ width: 0 }}
            animate={{ width: `${Math.max(barWidth, 2)}%` }}
            transition={{ duration: 0.6, delay: phase === 0 ? baseDelay + 0.1 : 0 }}
          />
        </div>

        <div className="flex flex-wrap items-center gap-2 w-full justify-start h-6">
          <AnimatePresence mode='popLayout'>
            {breakdown === null && (
              <motion.span
                key="no-answer"
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                exit={{ opacity: 0 }}
                transition={{ delay: baseDelay + 0.3 }}
                className="text-gray-400 font-medium text-sm"
              >
                No answer
              </motion.span>
            )}

            {breakdown && breakdown.penalty > 0 && phase >= 1 && (
              <PenaltyBadge key="penalty" points={breakdown.penalty} delay={0} />
            )}

            {breakdown && breakdown.basePoints > 0 && phase >= 1 && (
              <motion.div
                key="base-points"
                initial={{ scale: 0, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                transition={{ type: 'spring', stiffness: 500, damping: 15 }}
                className="flex items-center gap-1 px-2 py-0.5 rounded-full bg-green-500 text-white font-bold text-xs md:text-sm"
              >
                <span>+{breakdown.basePoints}</span>
              </motion.div>
            )}

            {breakdown && breakdown.streakBonus > 0 && phase >= 2 && (
              <BonusBadge
                key="streak"
                points={breakdown.streakBonus}
                label="Streak"
                icon={<Flame size={12} />}
                color="bg-amber-500"
                delay={0}
              />
            )}

            {breakdown && breakdown.comebackBonus > 0 && phase >= 3 && (
              <BonusBadge
                key="comeback"
                points={breakdown.comebackBonus}
                label="Comeback"
                icon={<Rocket size={12} />}
                color="bg-blue-500"
                delay={0}
              />
            )}

            {breakdown && breakdown.firstCorrectBonus > 0 && phase >= 4 && (
              <BonusBadge
                key="first-correct"
                points={breakdown.firstCorrectBonus}
                label="First!"
                icon={<Zap size={12} />}
                color="bg-yellow-500"
                delay={0}
              />
            )}
          </AnimatePresence>
        </div>
      </div>
    </motion.div>
  );
};

interface ScoreboardProps {
  players: Player[];
  onNext: () => void;
  isHost: boolean;
  currentPlayerId: string | null;
}

interface AnimatedPlayerState extends Player {
  displayName: string;
  currentScore: number;
  phase: number;
  initialIndex: number;
}

export const Scoreboard: React.FC<ScoreboardProps> = ({ players, onNext, isHost, currentPlayerId }) => {
  // Initialize players sorted by previousScore to start
  const [animatedPlayers, setAnimatedPlayers] = useState<AnimatedPlayerState[]>(() => {
    const playersWithMeta = players.map(p => ({
      ...p,
      displayName: p.id === currentPlayerId ? `${p.name} (You)` : p.name,
      currentScore: p.previousScore,
      phase: 0,
    }));
    
    // Sort by previous score initially (descending)
    // Add a secondary sort by ID to ensure stable sorting
    return playersWithMeta
      .sort((a, b) => (b.previousScore - a.previousScore) || a.id.localeCompare(b.id))
      .map((p, index) => ({
        ...p,
        initialIndex: index // Store the initial rank for staggered animation timing
      }));
  });

  useEffect(() => {
    const timers: NodeJS.Timeout[] = [];

    // We use the initial state to set up the timers
    // We can't use animatedPlayers in the dependency array or it will loop
    // But we need a reference to the initial setup to schedule things.
    // The state initializer runs once, so we need to reconstruct that list or trust the state is fresh on mount.
    // However, inside useEffect, animatedPlayers might change if we include it in deps.
    // We want to schedule based on the INITIAL state.
    
    // Let's grab the initial list again to be safe and consistent with the initializer logic
    const initialPlayers = players.map(p => ({
       ...p,
       previousScore: p.previousScore,
       pointsBreakdown: p.pointsBreakdown
    })).sort((a, b) => (b.previousScore - a.previousScore) || a.id.localeCompare(b.id));

    initialPlayers.forEach((player, initialIndex) => {
      const breakdown = player.pointsBreakdown;
      const baseDelay = initialIndex * 0.1;

      // Helper to update state
      const updatePlayerState = (phase: number, scoreToAdd: number) => {
        setAnimatedPlayers(prev => {
          const updated = prev.map(p => {
            if (p.id !== player.id) return p;
            return {
              ...p,
              phase,
              currentScore: p.currentScore + scoreToAdd
            };
          });
          // Re-sort on every update
          return updated.sort((a, b) => (b.currentScore - a.currentScore) || a.id.localeCompare(b.id));
        });
      };

      if (!breakdown) return;

      // Phase 1: Base Points + Penalty
      // (baseDelay + 0.2)s
      timers.push(setTimeout(() => {
        const points = breakdown.basePoints - breakdown.penalty;
        updatePlayerState(1, points);
      }, (baseDelay + 0.2) * 1000));

      // Phase 2: Streak
      // (baseDelay + 0.8)s
      if (breakdown.streakBonus > 0) {
        timers.push(setTimeout(() => {
          updatePlayerState(2, breakdown.streakBonus);
        }, (baseDelay + 0.8) * 1000));
      }

      // Phase 3: Comeback
      // (baseDelay + 1.2)s
      if (breakdown.comebackBonus > 0) {
        timers.push(setTimeout(() => {
          updatePlayerState(3, breakdown.comebackBonus);
        }, (baseDelay + 1.2) * 1000));
      }

      // Phase 4: First Correct
      // (baseDelay + 1.6)s
      if (breakdown.firstCorrectBonus > 0) {
        timers.push(setTimeout(() => {
          updatePlayerState(4, breakdown.firstCorrectBonus);
        }, (baseDelay + 1.6) * 1000));
      }
    });

    return () => timers.forEach(clearTimeout);
  }, []); // Run once on mount

  // Calculate max score based on FINAL scores (so the bar scale is consistent/correct relative to the winner)
  const maxScore = Math.max(...players.map(p => p.score), 1);

  return (
    <div className="flex flex-col h-screen p-4 md:p-8 overflow-hidden bg-theme-bg">
      <header className="text-center mb-4 md:mb-8 shrink-0">
        <h1 className="text-3xl md:text-5xl font-black text-white font-display drop-shadow-md">Scoreboard</h1>
      </header>

      <div className="flex-1 min-h-0 bg-white/95 backdrop-blur-sm rounded-2xl md:rounded-[3rem] shadow-[0_20px_50px_rgba(0,0,0,0.3)] p-4 md:p-8 text-gray-900 max-w-4xl w-full mx-auto relative z-10 border-4 md:border-8 border-white/50 overflow-y-auto custom-scrollbar">
        <LayoutGroup>
          <div className="space-y-3">
            {animatedPlayers.map((player, index) => (
              <PlayerRow 
                key={player.id} 
                player={player} 
                maxScore={maxScore} 
                rank={index + 1}
                currentScore={player.currentScore}
                phase={player.phase}
                baseDelay={player.initialIndex * 0.1}
              />
            ))}
          </div>
        </LayoutGroup>
      </div>

      <div className="mt-4 md:mt-8 flex justify-center md:justify-end max-w-4xl w-full mx-auto shrink-0 z-20">
        {isHost ? (
          <button
            onClick={onNext}
            className="bg-white text-theme-primary px-8 md:px-12 py-3 md:py-4 rounded-xl md:rounded-2xl text-xl md:text-2xl font-black shadow-[0_8px_0_rgba(0,0,0,0.2)] hover:scale-105 active:shadow-none active:translate-y-[8px] transition-all flex items-center gap-2"
          >
            Next <Trophy size={24} />
          </button>
        ) : (
          <div className="flex items-center gap-2 md:gap-3 bg-white/10 px-4 md:px-8 py-3 md:py-4 rounded-xl md:rounded-2xl backdrop-blur-md border-2 border-white/20 shadow-lg text-white">
            <Loader2 className="animate-spin w-6 h-6 md:w-8 md:h-8" />
            <span className="text-base md:text-xl font-bold">Waiting for host...</span>
          </div>
        )}
      </div>
    </div>
  );
};
