import { useState, useEffect, useRef, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'
import { motion, AnimatePresence } from 'motion/react'
import { IconX, IconMessagesFilled, IconCopyFilled,
         IconCircleFilled, IconBoltFilled, IconHeartFilled,
         IconArrowBigRightFilled, IconClockFilled, IconPlayerPlayFilled,
         IconConfettiFilled, IconChevronDownFilled } from '@tabler/icons-react'
import confetti from 'canvas-confetti'
import { useStore } from '../store'
import { useFocusTrap } from '../hooks/useFocusTrap'

interface RecentRoom {
  code: string
  mode: string
  ts: number
}

function loadRecentRooms(): RecentRoom[] {
  try {
    return JSON.parse(localStorage.getItem('mp-recent-rooms') || '[]')
  } catch { return [] }
}

function saveRecentRoom(code: string, mode: string) {
  const rooms = loadRecentRooms().filter(r => r.code !== code)
  rooms.unshift({ code, mode, ts: Date.now() })
  localStorage.setItem('mp-recent-rooms', JSON.stringify(rooms.slice(0, 8)))
}

export default function MultiplayerPanel({ onClose }: { onClose: () => void }) {
  const trapRef = useFocusTrap(true)
  const { t } = useTranslation()
  const puzzle = useStore(s => s.puzzle)
  const mpConnected = useStore(s => s.mpConnected)
  const mpRoomCode = useStore(s => s.mpRoomCode)
  const mpMode = useStore(s => s.mpMode)
  const mpPlayers = useStore(s => s.mpPlayers)
  const mpStarted = useStore(s => s.mpStarted)
  const mpCurrentTurn = useStore(s => s.mpCurrentTurn)
  const mpMyId = useStore(s => s.mpMyId)
  const mpIsCreator = useStore(s => s.mpIsCreator)
  const mpCreateRoom = useStore(s => s.mpCreateRoom)
  const mpJoinRoom = useStore(s => s.mpJoinRoom)
  const mpLeaveRoom = useStore(s => s.mpLeaveRoom)
  const mpStartGame = useStore(s => s.mpStartGame)
  const mpPassTurn = useStore(s => s.mpPassTurn)

  const partySubMode = useStore(s => s.partySubMode)

  const [joinCode, setJoinCode] = useState('')
  const [mode, setMode] = useState<'coop' | 'competitive' | 'party'>('coop')
  const [partySub, setPartySub] = useState<string>('wrong')
  const [partyDropOpen, setPartyDropOpen] = useState(false)
  const partyBtnRef = useRef<HTMLButtonElement>(null)
  const partyDropRef = useRef<HTMLDivElement>(null)
  const [partyDropPos, setPartyDropPos] = useState({ top: 0, left: 0, width: 0 })
  const [err, setErr] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [copied, setCopied] = useState(false)
  const [recentRooms, setRecentRooms] = useState<RecentRoom[]>(loadRecentRooms)

  const PARTY_MODES: { id: string; name: string; desc: string }[] = [
    { id: 'wrong', name: t('party.subModes.wrong'), desc: t('multiplayer.partyModes.wrongDesc') },
    { id: 'bluff', name: t('party.subModes.bluff'), desc: t('multiplayer.partyModes.bluffDesc') },
    { id: 'reverse', name: t('party.subModes.reverse'), desc: t('multiplayer.partyModes.reverseDesc') },
    { id: 'speed', name: t('party.subModes.speed'), desc: t('multiplayer.partyModes.speedDesc') },
    { id: 'roulette', name: t('party.subModes.roulette'), desc: t('multiplayer.partyModes.rouletteDesc') },
  ]

  const updatePartyDropPos = useCallback(() => {
    if (!partyBtnRef.current) return
    const rect = partyBtnRef.current.getBoundingClientRect()
    setPartyDropPos({ top: rect.bottom + 4, left: rect.left, width: rect.width })
  }, [])

  useEffect(() => {
    if (!partyDropOpen) return
    updatePartyDropPos()
    const onDown = (e: MouseEvent) => {
      const target = e.target
      if (target instanceof Node && partyDropRef.current && !partyDropRef.current.contains(target) &&
          partyBtnRef.current && !partyBtnRef.current.contains(target)) {
        setPartyDropOpen(false)
      }
    }
    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setPartyDropOpen(false) }
    window.addEventListener('scroll', updatePartyDropPos, true)
    document.addEventListener('mousedown', onDown)
    document.addEventListener('keydown', onKey)
    return () => {
      window.removeEventListener('scroll', updatePartyDropPos, true)
      document.removeEventListener('mousedown', onDown)
      document.removeEventListener('keydown', onKey)
    }
  }, [partyDropOpen, updatePartyDropPos])

  useEffect(() => {
    if (mpRoomCode && mpMode) {
      saveRecentRoom(mpRoomCode, mpMode)
      queueMicrotask(() => setRecentRooms(loadRecentRooms()))
    }
  }, [mpRoomCode, mpMode])

  const handleCreate = async () => {
    if (mode !== 'party' && !puzzle) return
    setErr(null)
    setBusy(true)
    try {
      await mpCreateRoom(mode, mode === 'party' ? partySub : undefined)
      if (mode === 'party') onClose()
    } catch (e) {
      setErr(e instanceof Error ? e.message : t('multiplayer.createFailed'))
    }
    setBusy(false)
  }

  const handleJoin = async (code?: string) => {
    const c = (code || joinCode).trim().toUpperCase()
    if (c.length < 4) return
    setErr(null)
    setBusy(true)
    try {
      await mpJoinRoom(c)
      onClose()
    } catch (e) {
      setErr(e instanceof Error ? e.message : t('multiplayer.joinFailed'))
    }
    setBusy(false)
  }

  const copyCode = () => {
    if (!mpRoomCode) return
    navigator.clipboard.writeText(mpRoomCode)
    setCopied(true)
    setTimeout(() => setCopied(false), 1500)
  }

  const inRoom = mpConnected && mpRoomCode
  const isMyTurn = mpStarted && mpCurrentTurn === mpMyId
  const currentPlayer = mpPlayers.find(p => p.id === mpCurrentTurn)

  return (
    <motion.div className="settings-overlay" onClick={onClose}
      initial={{ opacity: 0 }} animate={{ opacity: 1 }}
      exit={{ opacity: 0 }} transition={{ duration: 0.15 }}>
      <motion.div
        ref={trapRef}
        className="mp-panel"
        onClick={e => e.stopPropagation()}
        role="dialog" aria-modal="true" aria-label={t('multiplayer.playTogether')}
        initial={{ opacity: 0, scale: 0.96, y: 10 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.96, y: 10 }}
        transition={{ duration: 0.2 }}
      >
        <div className="mp-header">
          <h3><IconMessagesFilled size={16} /> {t('multiplayer.playTogether')}</h3>
          <button className="btn btn-sm btn-ghost" onClick={onClose} aria-label={t('common.close')}>
            <IconX size={14} aria-hidden="true" />
          </button>
        </div>

        <AnimatePresence>
          {err && (
            <motion.div className="mp-error" key="mp-err" role="alert"
              initial={{ opacity: 0, height: 0 }} animate={{ opacity: 1, height: 'auto' }}
              exit={{ opacity: 0, height: 0 }} transition={{ duration: 0.15 }}>
              {err}
            </motion.div>
          )}
        </AnimatePresence>

        {!inRoom ? (
          <div className="mp-lobby">
            <div className="mp-section">
              <div className="mp-section-title">{t('multiplayer.createRoom')}</div>
              <div className="mp-mode-picker mp-mode-picker-3">
                <button
                  className={`mp-mode-btn ${mode === 'coop' ? 'mp-mode-active' : ''}`}
                  aria-pressed={mode === 'coop'}
                  onClick={() => setMode('coop')}
                >
                  <IconHeartFilled size={16} aria-hidden="true" />
                  <span>{t('multiplayer.coop')}</span>
                </button>
                <button
                  className={`mp-mode-btn ${mode === 'competitive' ? 'mp-mode-active' : ''}`}
                  aria-pressed={mode === 'competitive'}
                  onClick={() => setMode('competitive')}
                >
                  <IconBoltFilled size={16} aria-hidden="true" />
                  <span>{t('multiplayer.race')}</span>
                </button>
                <button
                  className={`mp-mode-btn ${mode === 'party' ? 'mp-mode-active' : ''}`}
                  aria-pressed={mode === 'party'}
                  onClick={(e) => {
                    const wasParty = mode === 'party'
                    setMode('party')
                    if (wasParty) {
                      // already selected, do nothing
                    } else {
                      const rect = e.currentTarget.getBoundingClientRect()
                      if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
                        const canvas = document.createElement('canvas')
                        canvas.style.cssText = 'position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:9999'
                        document.body.appendChild(canvas)
                        const myConfetti = confetti.create(canvas, { resize: true })
                        myConfetti({
                          particleCount: 60,
                          spread: 70,
                          startVelocity: 25,
                          origin: {
                            x: (rect.left + rect.width / 2) / window.innerWidth,
                            y: (rect.top + rect.height / 2) / window.innerHeight,
                          },
                        }).then(() => canvas.remove())
                      }
                    }
                  }}
                >
                  <IconConfettiFilled size={16} aria-hidden="true" />
                  <span>{t('multiplayer.partyLabel')}</span>
                </button>
              </div>
              <AnimatePresence>
                {mode === 'party' && (
                  <motion.button type="button" key="party-sub" ref={partyBtnRef} className="mp-party-sub-selected"
                    aria-haspopup="listbox" aria-expanded={partyDropOpen}
                    onClick={() => setPartyDropOpen(!partyDropOpen)}
                    initial={{ opacity: 0, height: 0 }} animate={{ opacity: 1, height: 'auto' }}
                    exit={{ opacity: 0, height: 0 }} transition={{ duration: 0.15 }}
                    style={{ overflow: 'hidden' }}>
                    {PARTY_MODES.find(m => m.id === partySub)?.name || t('party.subModes.wrong')}
                    <IconChevronDownFilled size={10} style={{ transform: partyDropOpen ? 'rotate(180deg)' : 'none', transition: 'transform 150ms' }} aria-hidden="true" />
                  </motion.button>
                )}
              </AnimatePresence>
              {createPortal(
                <AnimatePresence>
                  {partyDropOpen && (
                    <motion.div
                      ref={partyDropRef}
                      className="mp-party-dropdown"
                      style={{ top: partyDropPos.top, left: partyDropPos.left, width: partyDropPos.width }}
                      initial={{ opacity: 0, y: -8 }}
                      animate={{ opacity: 1, y: 0 }}
                      exit={{ opacity: 0, y: -8 }}
                      transition={{ duration: 0.15 }}
                    >
                      {PARTY_MODES.map(m => (
                        <button
                          key={m.id}
                          className={`mp-party-drop-item ${partySub === m.id ? 'mp-party-drop-active' : ''}`}
                          onClick={() => { setPartySub(m.id); setPartyDropOpen(false) }}
                        >
                          <span className="mp-party-drop-name">{m.name}</span>
                          <span className="mp-party-drop-desc">{m.desc}</span>
                        </button>
                      ))}
                    </motion.div>
                  )}
                </AnimatePresence>,
                document.body,
              )}
              <button
                className="btn btn-primary"
                style={{ width: '100%' }}
                onClick={handleCreate}
                disabled={busy || (mode !== 'party' && !puzzle)}
              >
                {busy ? t('multiplayer.creating') : mode === 'party' ? t('multiplayer.startParty') : !puzzle ? t('multiplayer.loadPuzzleFirst') : t('multiplayer.createRoomBtn')}
              </button>
            </div>

            <div className="mp-section">
              <div className="mp-section-title">{t('multiplayer.joinRoom')}</div>
              <div className="mp-join-row">
                <input
                  className="mp-code-input"
                  value={joinCode}
                  onChange={e => setJoinCode(e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 6))}
                  placeholder={t('multiplayer.roomCode')}
                  aria-label={t('multiplayer.roomCode')}
                  maxLength={6}
                  spellCheck={false}
                  autoComplete="off"
                />
                <button
                  className="btn btn-primary"
                  onClick={() => handleJoin()}
                  disabled={busy || joinCode.length < 4}
                  aria-label={t('multiplayer.joinRoom')}
                >
                  <IconArrowBigRightFilled size={14} aria-hidden="true" />
                </button>
              </div>
            </div>

            {recentRooms.length > 0 && (
              <div className="mp-section">
                <div className="mp-section-title">{t('multiplayer.recentRooms')}</div>
                <div className="mp-recent">
                  {recentRooms.map(r => (
                    <button
                      key={r.code}
                      className="mp-recent-item"
                      onClick={() => handleJoin(r.code)}
                      disabled={busy}
                    >
                      <span className="mp-recent-code">{r.code}</span>
                      <span className="mp-recent-mode">{r.mode}</span>
                      <IconClockFilled size={10} aria-hidden="true" />
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>
        ) : (
          <div className="mp-room">
              <>
                <button type="button" className="mp-code-display" onClick={copyCode} aria-label={t('multiplayer.roomCode')}>
                  <span className="mp-code-label">{t('multiplayer.roomCode')}</span>
                  <span className="mp-code-value">{mpRoomCode}</span>
                  <span className="mp-code-copy">
                    {copied ? <span role="status">{t('multiplayer.copied')}</span> : <IconCopyFilled size={14} aria-hidden="true" />}
                  </span>
                </button>

                <div className="mp-room-mode">
                  {mpMode === 'party' ? <IconConfettiFilled size={14} /> : mpMode === 'coop' ? <IconHeartFilled size={14} /> : <IconBoltFilled size={14} />}
                  {mpMode === 'party' ? t('multiplayer.partyLabel') : mpMode === 'coop' ? t('multiplayer.coop') : t('multiplayer.race')}
                  {mpMode !== 'party' && <span className="mp-turn-label">- {t('multiplayer.turnBased')}</span>}
                  {mpMode === 'party' && <span className="mp-turn-label">- {
                    partySubMode === 'bluff' ? t('multiplayer.bluff') :
                    partySubMode === 'reverse' ? t('multiplayer.reverseClue') :
                    partySubMode === 'speed' ? t('multiplayer.speedRound') :
                    partySubMode === 'roulette' ? t('multiplayer.roulette') :
                    t('multiplayer.wrongAnswersOnly')
                  }</span>}
                </div>

                {mpStarted && currentPlayer && mpMode !== 'party' && (
                  <div className={`mp-turn-indicator ${isMyTurn ? 'mp-your-turn' : ''}`}>
                    <IconCircleFilled size={8} style={{ color: currentPlayer.color }} />
                    {isMyTurn ? t('multiplayer.yourTurn') : t('multiplayer.playerTurn', { name: currentPlayer.name })}
                  </div>
                )}

                {!mpStarted && (
                  <div className="mp-status">
                    <span className={`mp-status-dot ${mpConnected ? 'mp-connected' : 'mp-disconnected'}`} aria-hidden="true" />
                    {mpConnected ? t('multiplayer.waitingToStart') : t('multiplayer.disconnected')}
                  </div>
                )}

                <div className="mp-section-title">{t('party.players', { count: mpPlayers.length })}</div>
                <div className="mp-player-list">
                  {mpPlayers.map(p => (
                    <div key={p.id} className={`mp-player ${mpStarted && p.id === mpCurrentTurn ? 'mp-player-active' : ''}`}>
                      <IconCircleFilled size={10} style={{ color: p.color }} />
                      <span className="mp-player-name">{p.name}</span>
                      {p.id === mpMyId && <span className="mp-player-you">{t('multiplayer.you')}</span>}
                      {mpStarted && p.id === mpCurrentTurn && <span className="mp-player-turn">{t('multiplayer.playing')}</span>}
                    </div>
                  ))}
                  {mpPlayers.length === 0 && (
                    <div className="mp-empty">{t('multiplayer.waitingForPlayersEllipsis')}</div>
                  )}
                </div>

                <div className="mp-actions">
                  {!mpStarted && mpIsCreator && (
                    <button className="btn btn-primary btn-sm" onClick={mpStartGame} disabled={mpPlayers.length < 2} style={{ width: '100%' }}>
                      <IconPlayerPlayFilled size={14} /> {mpPlayers.length < 2 ? t('multiplayer.needMorePlayers') : t('multiplayer.startGame')}
                    </button>
                  )}
                  {mpStarted && isMyTurn && mpMode !== 'party' && (
                    <button className="btn btn-sm" onClick={mpPassTurn} style={{ width: '100%' }}>
                      {t('multiplayer.passTurn')}
                    </button>
                  )}
                  <button className="btn btn-sm mp-leave" onClick={() => { mpLeaveRoom(); }}>
                    <IconX size={14} /> {t('multiplayer.leaveRoom')}
                  </button>
                </div>
              </>
          </div>
        )}
      </motion.div>
    </motion.div>
  )
}
