import { useState, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { motion, AnimatePresence } from 'motion/react'
import { IconCrownFilled, IconTrophyFilled,
         IconCircleFilled, IconCheckFilled, IconSendFilled,
         IconBoltFilled } from '@tabler/icons-react'
import { useStore } from '../store'

const MODE_COLORS = {
  wrong: '#e8594a',
  bluff: '#8b5cf6',
  reverse: '#3b82f6',
  speed: '#f59e0b',
  roulette: '#22c55e',
}

function modeColorFor(colors: Record<string, string>, mode: string): string {
  return colors[mode] ?? colors.wrong
}

function Countdown({ deadline }: { deadline: number | null }) {
  const [secs, setSecs] = useState(0)

  useEffect(() => {
    if (!deadline) return
    const tick = () => {
      const left = Math.max(0, Math.ceil((deadline - Date.now()) / 1000))
      setSecs(left)
    }
    tick()
    const id = setInterval(tick, 250)
    return () => clearInterval(id)
  }, [deadline])

  const urgent = secs > 0 && secs <= 5

  return (
    <div className={`party-timer ${urgent ? 'party-timer-urgent' : ''}`} role="timer" aria-live={urgent ? 'assertive' : 'off'}>
      {secs}
    </div>
  )
}

function Scoreboard({ scores, myId }: { scores: { id: string; name: string; color: string; score: number }[]; myId: string | null }) {
  const { t } = useTranslation()
  const sorted = [...scores].sort((a, b) => b.score - a.score)
  return (
    <div className="party-scoreboard">
      <div className="party-scoreboard-title">{t('party.scores')}</div>
      {sorted.map((p, i) => (
        <div key={p.id} className={`party-score-row ${p.id === myId ? 'party-score-you' : ''}`}>
          {i === 0 && scores.length > 1 && p.score > 0 && <span aria-label={t('party.firstPlace')}><IconCrownFilled size={10} style={{ color: '#fbbf24' }} /></span>}
          <IconCircleFilled size={8} style={{ color: p.color }} aria-hidden="true" />
          <span className="party-score-name">{p.name}</span>
          <span className="party-score-pts">{p.score}</span>
        </div>
      ))}
    </div>
  )
}

function SubmitPhase({ prompt, placeholder, maxLen }: { prompt: string; placeholder: string; maxLen?: number }) {
  const { t } = useTranslation()
  const clue = useStore(s => s.partyClue)
  const mySubmission = useStore(s => s.partyMySubmission)
  const submitAnswer = useStore(s => s.partySubmitAnswer)
  const [draft, setDraft] = useState('')
  const inputRef = useRef<HTMLInputElement>(null)
  const phase = useStore(s => s.partyPhase)
  const round = useStore(s => s.partyRound)
  const max = maxLen || 50

  useEffect(() => {
    if (phase === 'submit') {
      queueMicrotask(() => setDraft(''))
      setTimeout(() => inputRef.current?.focus(), 100)
    }
  }, [phase, round])

  const handleSubmit = () => {
    const text = draft.trim()
    if (!text || mySubmission) return
    submitAnswer(text)
  }

  return (
    <motion.div
      key="submit"
      className="party-phase-content"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
    >
      <div className="party-phase-label">{prompt}</div>
      <div className="party-clue">{clue}</div>

      <AnimatePresence mode="wait">
        {!mySubmission ? (
          <motion.div key="input" className="party-submit-area"
            initial={{ opacity: 0 }} animate={{ opacity: 1 }}
            exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
            <div className="party-input-wrap">
              <input
                ref={inputRef}
                className="party-input"
                value={draft}
                onChange={e => setDraft(e.target.value.slice(0, max))}
                onKeyDown={e => { if (e.key === 'Enter') handleSubmit() }}
                placeholder={placeholder}
                aria-label={placeholder}
                maxLength={max}
                spellCheck={false}
              />
              <span className="party-char-count">{draft.length}/{max}</span>
            </div>
            <button
              className="btn btn-primary party-submit-btn"
              onClick={handleSubmit}
              disabled={!draft.trim()}
            >
              <IconSendFilled size={14} aria-hidden="true" /> {t('party.submit')}
            </button>
          </motion.div>
        ) : (
          <motion.div key="submitted"
            className="party-submitted"
            initial={{ scale: 0.9, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            exit={{ opacity: 0, scale: 0.9 }}
            transition={{ duration: 0.15 }}
          >
            <IconCheckFilled size={16} aria-hidden="true" />
            <span>{t('party.submittedWaiting')}</span>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  )
}

function VotePhase({ prompt }: { prompt: string }) {
  const { t } = useTranslation()
  const clue = useStore(s => s.partyClue)
  const answers = useStore(s => s.partyAnswers)
  const myVote = useStore(s => s.partyMyVote)
  const voteAnswer = useStore(s => s.partyVoteAnswer)

  const handleVote = (id: string) => {
    if (myVote) return
    voteAnswer(id)
  }

  return (
    <motion.div
      key="vote"
      className="party-phase-content"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
    >
      <div className="party-phase-label">{prompt}</div>
      <div className="party-clue party-clue-sm">{clue}</div>
      <div className="party-answers">
        {answers.map((a, i) => (
          <motion.button
            key={a.id}
            className={`party-answer-card ${myVote === a.id ? 'party-answer-selected' : ''}`}
            onClick={() => handleVote(a.id)}
            disabled={!!myVote}
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ delay: i * 0.06 }}
            whileHover={!myVote ? { scale: 1.02 } : undefined}
            whileTap={!myVote ? { scale: 0.97 } : undefined}
          >
            <span className="party-answer-text">{a.text}</span>
            {myVote === a.id && <IconCheckFilled size={14} className="party-answer-check" />}
          </motion.button>
        ))}
      </div>
      <AnimatePresence>
        {myVote && (
          <motion.div className="party-voted"
            initial={{ opacity: 0 }} animate={{ opacity: 1 }}
            exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
            {t('party.voteLocked')}
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  )
}

function ResultsPhase({ realLabel }: { realLabel?: string }) {
  const { t } = useTranslation()
  const clue = useStore(s => s.partyClue)
  const results = useStore(s => s.partyResults)
  const realAnswer = useStore(s => s.partyRealAnswer)
  if (!results) return null
  const label = realLabel || t('party.resultLabels.realAnswer')

  return (
    <motion.div
      key="results"
      className="party-phase-content"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
    >
      <div className="party-phase-label">{t('party.results')}</div>
      <div className="party-clue party-clue-sm">{clue}</div>
      {realAnswer && (
        <motion.div
          className="party-real-answer"
          initial={{ opacity: 0, scale: 0.9 }}
          animate={{ opacity: 1, scale: 1 }}
          transition={{ delay: 0.2 }}
        >
          {label}: <span className="party-real-answer-word">{realAnswer}</span>
        </motion.div>
      )}
      <div className="party-results-list">
        {[...results].sort((a, b) => b.votes - a.votes).map((r, i) => {
          const maxVotes = Math.max(1, ...results.map(x => x.votes))
          return (
            <motion.div
              key={r.id}
              className={`party-result ${r.isReal ? 'party-result-real' : ''} ${i === 0 && r.votes > 0 && !r.isReal ? 'party-result-top' : ''}`}
              initial={{ opacity: 0, x: -15 }}
              animate={{ opacity: 1, x: 0 }}
              transition={{ delay: i * 0.08 }}
            >
              <div className="party-result-header">
                <span className="party-result-author" style={{ color: r.authorColor }}>
                  <IconCircleFilled size={8} aria-hidden="true" /> {r.isReal ? label : r.author}
                </span>
                <span className="party-result-votes">
                  {r.votes} {r.votes === 1 ? t('party.vote') : t('party.votes')}
                </span>
              </div>
              <div className="party-result-text">{r.text}</div>
              <div className="party-result-bar-track">
                <motion.div
                  className="party-result-bar-fill"
                  initial={{ width: 0 }}
                  animate={{ width: `${(r.votes / maxVotes) * 100}%` }}
                  transition={{ duration: 0.5, delay: i * 0.08 + 0.2 }}
                  style={{ background: r.isReal ? 'var(--correct)' : r.authorColor }}
                />
              </div>
            </motion.div>
          )
        })}
      </div>
    </motion.div>
  )
}

function SpeedRacePhase() {
  const { t } = useTranslation()
  const clue = useStore(s => s.partyClue)
  const correctPlayers = useStore(s => s.partyCorrectPlayers)
  const speedAnswer = useStore(s => s.partySpeedAnswer)
  const myId = useStore(s => s.mpMyId)
  const [draft, setDraft] = useState('')
  const [, setSent] = useState(false)
  const inputRef = useRef<HTMLInputElement>(null)
  const phase = useStore(s => s.partyPhase)
  const round = useStore(s => s.partyRound)

  useEffect(() => {
    if (phase === 'race') {
      queueMicrotask(() => { setDraft(''); setSent(false) })
      setTimeout(() => inputRef.current?.focus(), 100)
    }
  }, [phase, round])

  const alreadyCorrect = correctPlayers.some(p => p.id === myId)

  const handleSubmit = () => {
    const text = draft.trim()
    if (!text || alreadyCorrect) return
    speedAnswer(text)
    setDraft('')
    setSent(true)
    setTimeout(() => setSent(false), 500)
  }

  return (
    <motion.div
      key="race"
      className="party-phase-content"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
    >
      <div className="party-phase-label">{t('party.typeAnswer')}</div>
      <div className="party-clue">{clue}</div>

      <AnimatePresence mode="wait">
        {alreadyCorrect ? (
          <motion.div key="correct"
            className="party-submitted"
            initial={{ scale: 0.9, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            exit={{ opacity: 0, scale: 0.9 }}
            transition={{ duration: 0.15 }}
          >
            <IconCheckFilled size={16} aria-hidden="true" />
            <span>{t('party.correct')}</span>
          </motion.div>
        ) : (
          <motion.div key="speed-input" className="party-submit-area"
            initial={{ opacity: 0 }} animate={{ opacity: 1 }}
            exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
            <div className="party-input-wrap">
              <input
                ref={inputRef}
                className="party-input"
                value={draft}
                onChange={e => setDraft(e.target.value.toUpperCase().replace(/[^A-Z]/g, '').slice(0, 20))}
                onKeyDown={e => { if (e.key === 'Enter') handleSubmit() }}
                placeholder={t('party.yourAnswer')}
                aria-label={t('party.yourAnswer')}
                maxLength={20}
                spellCheck={false}
              />
            </div>
            <button
              className="btn btn-primary party-submit-btn"
              onClick={handleSubmit}
              disabled={!draft.trim()}
            >
              <IconBoltFilled size={14} aria-hidden="true" /> {t('party.go')}
            </button>
          </motion.div>
        )}
      </AnimatePresence>

      <AnimatePresence>
        {correctPlayers.length > 0 && (
          <motion.div key="feed" className="party-speed-feed"
            initial={{ opacity: 0 }} animate={{ opacity: 1 }}
            exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
            <AnimatePresence>
              {correctPlayers.map(p => (
                <motion.div
                  key={p.id}
                  className="party-speed-correct"
                  initial={{ opacity: 0, x: -10 }}
                  animate={{ opacity: 1, x: 0 }}
                  exit={{ opacity: 0, x: -10 }}
                  transition={{ duration: 0.15 }}
                >
                  <IconCircleFilled size={8} style={{ color: p.color }} aria-hidden="true" />
                  <span>{p.name}</span>
                  <span className="party-speed-pts">+{p.points}</span>
                </motion.div>
              ))}
            </AnimatePresence>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  )
}

function RouletteChoosePhase() {
  const { t } = useTranslation()
  const clue = useStore(s => s.partyClue)
  const choices = useStore(s => s.partyChoices)
  const myPick = useStore(s => s.partyMyPick)
  const pickChoice = useStore(s => s.partyPickChoice)

  return (
    <motion.div
      key="choose"
      className="party-phase-content"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
    >
      <div className="party-phase-label">{t('party.pickDefinition')}</div>
      <div className="party-clue">{clue}</div>
      <div className="party-roulette-options">
        {choices.map((c, i) => (
          <motion.button
            key={c.id}
            className={`party-roulette-option ${myPick === c.id ? 'party-roulette-picked' : ''}`}
            onClick={() => !myPick && pickChoice(c.id)}
            disabled={!!myPick}
            initial={{ opacity: 0, y: 12 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ delay: i * 0.08 }}
            whileHover={!myPick ? { scale: 1.02 } : undefined}
            whileTap={!myPick ? { scale: 0.97 } : undefined}
          >
            <span className="party-roulette-label">{c.label}</span>
            <span className="party-roulette-text">{c.text}</span>
            {myPick === c.id && <IconCheckFilled size={14} className="party-answer-check" />}
          </motion.button>
        ))}
      </div>
      <AnimatePresence>
        {myPick && (
          <motion.div className="party-voted"
            initial={{ opacity: 0 }} animate={{ opacity: 1 }}
            exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
            {t('party.lockedIn')}
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  )
}

export default function PartyGame() {
  const { t } = useTranslation()
  const phase = useStore(s => s.partyPhase)
  const round = useStore(s => s.partyRound)
  const totalRounds = useStore(s => s.partyTotalRounds)
  const deadline = useStore(s => s.partyDeadline)
  const scores = useStore(s => s.partyScores)
  const myId = useStore(s => s.mpMyId)
  const subMode = useStore(s => s.partySubMode)
  const realAnswer = useStore(s => s.partyRealAnswer)

  const liveText = useMemo(() => {
    if (phase === 'submit' || phase === 'vote' || phase === 'race' || phase === 'choose') {
      return t('party.phaseAnnounce', { phase, current: round, total: totalRounds })
    } else if (phase === 'results') {
      return t('party.resultsAnnounce', { answer: realAnswer || '' })
    } else if (phase === 'finished') {
      return t('party.gameOver')
    }
    return null
  }, [phase, round, realAnswer, totalRounds, t])

  const subLabels = {
    wrong: t('party.subModes.wrong'),
    bluff: t('party.subModes.bluff'),
    reverse: t('party.subModes.reverse'),
    speed: t('party.subModes.speed'),
    roulette: t('party.subModes.roulette'),
  }

  const subLabelFor = (labels: Record<string, string>, mode: string): string => {
    return labels[mode] ?? labels.wrong
  }
  const finishedColor = modeColorFor(MODE_COLORS, subMode || 'wrong')
  const finishedTitle = subLabelFor(subLabels, subMode || 'wrong')

  if (phase === 'finished') {
    const sorted = [...scores].sort((a, b) => b.score - a.score)
    const winner = sorted[0]
    return (
      <motion.div className="party-game"
        initial={{ opacity: 0 }} animate={{ opacity: 1 }}
        transition={{ duration: 0.25 }}>
        <div className="party-final">
          <motion.div
            className="party-final-header"
            initial={{ scale: 0.8, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            transition={{ duration: 0.4 }}
          >
            <IconTrophyFilled size={32} style={{ color: '#fbbf24' }} aria-hidden="true" />
            <h2 style={{ color: finishedColor }}>{finishedTitle}</h2>
          </motion.div>
          <div className="party-final-list">
            {sorted.map((p, i) => (
              <motion.div
                key={p.id}
                className={`party-final-row ${i === 0 ? 'party-final-winner' : ''}`}
                initial={{ x: -20, opacity: 0 }}
                animate={{ x: 0, opacity: 1 }}
                transition={{ delay: i * 0.1 }}
              >
                <span className="party-final-rank">
                  {i === 0 && winner ? <span aria-label={t('party.firstPlace')}><IconCrownFilled size={14} style={{ color: '#fbbf24' }} /></span> : `#${i + 1}`}
                </span>
                <IconCircleFilled size={10} style={{ color: p.color }} aria-hidden="true" />
                <span className="party-final-name">{p.name}</span>
                <span className="party-final-pts">{p.score}</span>
              </motion.div>
            ))}
          </div>
        </div>
      </motion.div>
    )
  }

  const submitPrompt = subMode === 'bluff' ? t('party.prompts.fakeDefinition')
    : subMode === 'reverse' ? t('party.prompts.writeClue')
    : t('party.prompts.wrongAnswer')

  const submitPlaceholder = subMode === 'bluff' ? t('party.placeholders.soundReal')
    : subMode === 'reverse' ? t('party.placeholders.bestClue')
    : t('party.placeholders.funniestWrong')

  const votePrompt = subMode === 'bluff' ? t('party.prompts.realDefinition')
    : subMode === 'reverse' ? t('party.prompts.voteBestClue')
    : t('party.prompts.voteFunniest')

  const resultLabel = subMode === 'bluff' ? t('party.resultLabels.realDefinition')
    : subMode === 'reverse' ? t('party.resultLabels.originalClue')
    : subMode === 'roulette' ? t('party.correct')
    : t('party.resultLabels.realAnswer')

  const modeColor = modeColorFor(MODE_COLORS, subMode || 'wrong')
  const modeTitle = subLabelFor(subLabels, subMode || 'wrong')

  return (
    <div className="party-game">
      <div className="visually-hidden" aria-live="polite">{liveText}</div>
      <div className="party-main">
        <h2 className="party-mode-title" style={{ color: modeColor }}>{modeTitle}</h2>
        <div className="party-round">{t('party.round', { current: round, total: totalRounds })}</div>
        <Countdown deadline={deadline} />

        <AnimatePresence mode="wait">
          {phase === 'submit' && (
            <SubmitPhase
              prompt={submitPrompt}
              placeholder={submitPlaceholder}
              maxLen={subMode === 'bluff' ? 80 : 50}
            />
          )}

          {phase === 'vote' && <VotePhase prompt={votePrompt} />}

          {phase === 'race' && <SpeedRacePhase />}

          {phase === 'choose' && <RouletteChoosePhase />}

          {phase === 'results' && <ResultsPhase realLabel={resultLabel} />}
        </AnimatePresence>
      </div>

      <AnimatePresence>
        {scores.length > 0 && phase !== 'finished' && (
          <motion.div key="scoreboard"
            initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: 10 }} transition={{ duration: 0.2 }}>
            <Scoreboard scores={scores} myId={myId} />
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  )
}
