import { useState, useEffect, useCallback, useRef } from 'react'
import Header from './components/Header'
import NameModal from './components/NameModal'
import TabBar from './components/TabBar'
import OptionList from './components/OptionList'
import ResultsTab from './components/ResultsTab'
import AddOption from './components/AddOption'
import Toast from './components/Toast'
import WsOverlay from './components/WsOverlay'
import OptionModal from './components/OptionModal'
import YourVotesModal from './components/YourVotesModal'
import SocialToast from './components/SocialToast'
import MapTab from './components/MapTab'
import BudgetTab from './components/BudgetTab'
import { useWebSocket } from './hooks/useWebSocket'
import { useVoterSession } from './hooks/useVoterSession'
import { useSound } from './hooks/useSound'
import './App.css'

const SOUND_KEY = 'cabo-voting-sound'
const THEME_KEY = 'cabo-voting-theme'

export default function App() {
  const [categories, setCategories] = useState([])
  const [options, setOptions] = useState([])
  const [pollsOpen, setPollsOpen] = useState(true)
  const [totalVoters, setTotalVoters] = useState(0)
  const [activeTab, setActiveTab] = useState('hotel')
  const [toast, setToast] = useState(null)
  const [selectedOption, setSelectedOption] = useState(null)   // detail modal
  const [yourVotesOpen, setYourVotesOpen] = useState(false)      // your votes modal
  const [socialToast, setSocialToast] = useState(null)            // floating vote toast
  const [soundEnabled, setSoundEnabled] = useState(() => localStorage.getItem(SOUND_KEY) !== 'off')
  const [theme, setTheme] = useState(() => localStorage.getItem(THEME_KEY) || 'dark')
  const [onlineCount, setOnlineCount] = useState(0)
  const [pollDeadline, setPollDeadline] = useState(null)

  const socialToastTimer = useRef(null)
  const { voterName, setVoterName, clearVoter } = useVoterSession()
  const { playVoteSound, playRemoveSound } = useSound()

  const pollsExpired = pollDeadline && Date.now() > new Date(pollDeadline).getTime()

  const { wsRef, wsConnected, reconnect } = useWebSocket({
    setCategories, setOptions, setPollsOpen, setTotalVoters,
    setOnlineCount, setPollDeadline,
  })

  // Apply theme to body
  useEffect(() => {
    document.body.dataset.theme = theme
    localStorage.setItem(THEME_KEY, theme)
  }, [theme])

  const showToast = useCallback((msg, type = '') => {
    setToast({ msg, type })
    setTimeout(() => setToast(null), 3000)
  }, [])

  const handleVote = useCallback((option, removed = false) => {
    if (!voterName) return
    if (!pollsOpen || pollsExpired) return
    const opt = options.find(o => o.id === option.id)
    if (!opt) return

    const alreadyVoted = opt.votes?.some(v => v.name === voterName)

    // Optimistic update
    setOptions(prev => prev.map(o => {
      if (o.id !== option.id) return o
      if (removed || alreadyVoted) {
        return { ...o, votes: o.votes.filter(v => v.name !== voterName) }
      } else {
        return { ...o, votes: [...(o.votes || []), { name: voterName, timestamp: Date.now() }] }
      }
    }))

    const ws = wsRef.current
    if (ws?.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'vote', optionId: option.id, voterName, remove: removed || alreadyVoted }))
    }

    if (removed || alreadyVoted) {
      playRemoveSound()
      showToast(`Removed vote for ${opt.name}`)
    } else {
      playVoteSound()
      showToast(`Voted for ${opt.name}!`)
    }

    // Social toast for others (shows voter name + option name)
    setSocialToast({ voterName, optionName: opt.name, categoryId: opt.categoryId })
    clearTimeout(socialToastTimer.current)
    socialToastTimer.current = setTimeout(() => setSocialToast(null), 3000)
  }, [voterName, options, pollsOpen, pollsExpired, wsRef, playVoteSound, playRemoveSound, showToast])

  const handleRemoveVote = useCallback((optionId) => {
    const opt = options.find(o => o.id === optionId)
    if (opt) handleVote(opt, true)
  }, [options, handleVote])

  // Check URL params on load
  useEffect(() => {
    const params = new URLSearchParams(location.search)
    if (params.get('view') === 'results') setActiveTab('results')
    const optionId = params.get('option')
    if (optionId) {
      // Wait for options to load, then open modal
      const check = () => {
        const opt = options.find(o => o.id === optionId)
        if (opt) { setSelectedOption(opt); } else if (options.length > 0) { setSelectedOption(null) }
      }
      check()
    }
  }, [])  // eslint-disable-line

  const handleAddSubmit = useCallback((data) => {
    if (!voterName) { showToast('Enter your name first', 'error'); return }
    const ws = wsRef.current
    if (ws?.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'add_option', ...data, voterName }))
    }
    document.getElementById('add-name').value = ''
    document.getElementById('add-desc').value = ''
    document.getElementById('add-url').value = ''
    showToast(`Submitted "${data.name}" for approval!`, 'success')
  }, [voterName, wsRef, showToast])

  const toggleSound = useCallback(() => {
    setSoundEnabled(prev => {
      const next = !prev
      localStorage.setItem(SOUND_KEY, next ? 'on' : 'off')
      return next
    })
  }, [])

  const toggleTheme = useCallback(() => {
    setTheme(prev => prev === 'dark' ? 'light' : 'dark')
  }, [])

  const votingCats = categories.filter(c => c.id !== 'results')
  const optionCounts = votingCats.reduce((acc, cat) => {
    acc[cat.id] = options.filter(o => o.categoryId === cat.id).length
    return acc
  }, {})

  // "Your Votes" — all options this voter voted for
  const yourVotes = options.filter(o => o.votes?.some(v => v.name === voterName))

  return (
    <>
      <a className="skip-link" href="#main">Skip to content</a>

      <Header
        voterName={voterName}
        pollsOpen={pollsOpen}
        totalVoters={totalVoters}
        wsConnected={wsConnected}
        onChangeName={clearVoter}
        soundEnabled={soundEnabled}
        onToggleSound={toggleSound}
        theme={theme}
        onToggleTheme={toggleTheme}
        onlineCount={onlineCount}
        pollDeadline={pollDeadline}
        pollsExpired={pollsExpired}
      />

      {!voterName && <NameModal onSubmit={setVoterName} />}

      <TabBar
        categories={categories}
        activeTab={activeTab}
        onTab={setActiveTab}
        optionCounts={optionCounts}
        onYourVotes={() => setYourVotesOpen(true)}
        voterName={voterName}
        yourVotesCount={yourVotes.length}
      />

      <main id="main">
        {activeTab === 'results' ? (
          <ResultsTab
            categories={categories}
            options={options}
            pollsOpen={pollsOpen}
            totalVoters={totalVoters}
          />
        ) : activeTab === 'map' ? (
          <MapTab
            options={options}
            categories={categories}
            onSelectOption={setSelectedOption}
          />
        ) : activeTab === 'budget' ? (
          <BudgetTab
            options={options}
            categories={categories}
          />
        ) : (
          <OptionList
            options={options.filter(o => o.categoryId === activeTab && o.approved)}
            voterName={voterName}
            pollsOpen={pollsOpen}
            pollsExpired={pollsExpired}
            onVote={handleVote}
            onCardClick={setSelectedOption}
            categoryId={activeTab}
          />
        )}

        {activeTab !== 'results' && activeTab !== 'map' && activeTab !== 'budget' && (
          <AddOption
            categories={categories}
            voterName={voterName}
            onSubmit={handleAddSubmit}
            onNeedsName={() => showToast('Enter your name first', 'error')}
          />
        )}
      </main>

      {/* Option detail modal */}
      {selectedOption && (
        <OptionModal
          option={selectedOption}
          voterName={voterName}
          onClose={() => setSelectedOption(null)}
          onVote={handleVote}
          categories={categories}
        />
      )}

      {/* Your votes modal */}
      {yourVotesOpen && (
        <YourVotesModal
          votes={yourVotes}
          voterName={voterName}
          onClose={() => setYourVotesOpen(false)}
          onRemoveVote={handleRemoveVote}
          onViewOption={setSelectedOption}
          categories={categories}
        />
      )}

      <WsOverlay connected={wsConnected} onReconnect={reconnect} />
      {toast && <Toast msg={toast.msg} type={toast.type} />}
      {socialToast && (
        <SocialToast
          voterName={socialToast.voterName}
          optionName={socialToast.optionName}
          categoryId={socialToast.categoryId}
        />
      )}
    </>
  )
}
