import { useState, useEffect, useRef } from 'react'
import { ROUTES, WAYPOINTS, OTIUM_DURATION_MS } from '../constants.js'
import {
  applyDispatch,
  applyDispatchCost,
  applyOtium,
  getNewJournalEntry,
  getSeenJournalEntries,
  isRouteUnlocked,
  getChapter,
} from '../gameState.js'

const CHAPTERS = ['ostia', 'capua', 'brundisium', 'carthago', 'alexandria']

export default function Game({ state, onStateChange, onNewGame }) {
  const [selectedRoute, setSelectedRoute] = useState(null)
  const [dispatch, setDispatch] = useState(null)
  const [otium, setOtium] = useState(null)
  const [message, setMessage] = useState('')
  const [journal, setJournal] = useState(getSeenJournalEntries(state))
  const [newEntryKey, setNewEntryKey] = useState(null)
  const tickRef = useRef(null)
  const msgRef = useRef(null)

  function showMessage(text, dur = 3500) {
    setMessage(text)
    clearTimeout(msgRef.current)
    msgRef.current = setTimeout(() => setMessage(''), dur)
  }

  useEffect(() => {
    tickRef.current = setInterval(() => {
      const now = Date.now()

      if (dispatch) {
        const elapsed = now - dispatch.startMs
        if (elapsed >= dispatch.durationMs) {
          setDispatch(null)
          const entry = getNewJournalEntry(state, dispatch.routeId)
          const newState = applyDispatch(state, dispatch.routeId)
          const route = ROUTES.find((r) => r.id === dispatch.routeId)
          showMessage(`Galley returned. +${route.profit} denarii.`)
          if (entry) {
            setJournal((j) => [entry, ...j])
            setNewEntryKey(`${dispatch.routeId}-${newState.route_dispatches[dispatch.routeId]}`)
            setTimeout(() => setNewEntryKey(null), 5000)
          }
          setSelectedRoute(null)
          onStateChange(newState)
        }
      }

      if (otium) {
        const elapsed = now - otium.startMs
        if (elapsed >= OTIUM_DURATION_MS) {
          setOtium(null)
          const newState = applyOtium(state)
          const gain = newState.aut - state.aut
          showMessage(`Otium complete. +${gain} auctoritas.`)
          onStateChange(newState)
        }
      }
    }, 250)

    return () => clearInterval(tickRef.current)
  }, [dispatch, otium, state, onStateChange])

  function handleSelectRoute(routeId) {
    if (dispatch || otium) return
    if (!isRouteUnlocked(state, routeId)) return
    setSelectedRoute((prev) => prev === routeId ? null : routeId)
  }

  function handleDispatch() {
    if (!selectedRoute) { showMessage('Select a trade route first.'); return }
    if (dispatch) { showMessage('A galley is already at sea.'); return }
    if (otium) { showMessage('Finish your otium first.'); return }
    const route = ROUTES.find((r) => r.id === selectedRoute)
    if (state.den < route.cost) { showMessage('Not enough denarii for this voyage.'); return }
    const newState = applyDispatchCost(state, selectedRoute)
    onStateChange(newState)
    setDispatch({ routeId: selectedRoute, startMs: Date.now(), durationMs: route.duration_ms })
    showMessage(`Galley dispatched on ${route.from} → ${route.to}.`)
  }

  function handleOtium() {
    if (dispatch) { showMessage('Your galley is at sea. Wait for it to return.'); return }
    if (otium) return
    setOtium({ startMs: Date.now() })
    showMessage('You rest. The harbour sounds fade.')
  }

  function handleNewGame() {
    if (!window.confirm('Abandon this ledger and begin a new one?')) return
    onNewGame()
  }

  let progressPct = 0
  let progressLabel = ''
  let progressSub = ''
  let isOtium = false

  if (dispatch) {
    const elapsed = Date.now() - dispatch.startMs
    progressPct = Math.min((elapsed / dispatch.durationMs) * 100, 100)
    const route = ROUTES.find((r) => r.id === dispatch.routeId)
    progressLabel = `${WAYPOINTS[route.from].name} → ${WAYPOINTS[route.to].name}`
    progressSub = `${Math.round(progressPct)}%`
  } else if (otium) {
    const elapsed = Date.now() - otium.startMs
    progressPct = Math.min((elapsed / OTIUM_DURATION_MS) * 100, 100)
    progressLabel = 'resting...'
    progressSub = `${Math.round(progressPct)}%`
    isOtium = true
  }

  const chapter = getChapter(state.den, state.aut)
  const currentLocation = WAYPOINTS[CHAPTERS[chapter - 1]]
  const busy = !!dispatch || !!otium

  return (
    <div className="game">
      <header className="game-header">
        <h1 className="game-title">OTIVM</h1>
        <p className="game-subtitle">mercator romanus · anno DCCXL ab urbe condita</p>
      </header>

      <div className="journey">
        {CHAPTERS.map((id, i) => {
          const wp = WAYPOINTS[id]
          const ch = i + 1
          const cls = ch < chapter ? 'reached' : ch === chapter ? 'current' : ''
          return (
            <span key={id}>
              <span className={`journey-node ${cls}`}>{wp.name}</span>
              {i < CHAPTERS.length - 1 && (
                <span className="journey-arrow"> › </span>
              )}
            </span>
          )
        })}
      </div>

      <div className="stats">
        <div className="stat">
          <div className="stat-label">Denarii</div>
          <div className="stat-value">{Math.floor(state.den).toLocaleString()}</div>
          <div className="stat-sub">in the strongbox</div>
        </div>
        <div className="stat">
          <div className="stat-label">Auctoritas</div>
          <div className="stat-value">{Math.floor(state.aut)}</div>
          <div className="stat-sub">reputation</div>
        </div>
        <div className="stat">
          <div className="stat-label">Dispatches</div>
          <div className="stat-value">{state.dispatches}</div>
          <div className="stat-sub">completed</div>
        </div>
        <div className="stat">
          <div className="stat-label">Location</div>
          <div className="stat-value" style={{ fontSize: '0.95rem', paddingTop: '4px' }}>
            {currentLocation.name}
          </div>
          <div className="stat-sub">chapter {['I','II','III','IV','V'][chapter - 1]}</div>
        </div>
      </div>

      {(dispatch || otium) && (
        <div className="progress-wrap">
          <div className="progress-label">
            <span>{progressLabel}</span>
            <span>{progressSub}</span>
          </div>
          <div className="progress-track">
            <div
              className={`progress-fill${isOtium ? ' otium' : ''}`}
              style={{ width: `${progressPct.toFixed(1)}%` }}
            />
          </div>
        </div>
      )}

      <div className="message">{message}</div>

      <p className="section-title">Trade routes</p>
      <div className="route-grid">
        {ROUTES.map((route) => {
          const unlocked = isRouteUnlocked(state, route.id)
          const selected = selectedRoute === route.id
          const fromWp = WAYPOINTS[route.from]
          const toWp = WAYPOINTS[route.to]
          return (
            <div
              key={route.id}
              className={`route-card${!unlocked ? ' locked' : ''}${selected ? ' selected' : ''}`}
              onClick={() => handleSelectRoute(route.id)}
            >
              <div className="route-name">{fromWp.name} → {toWp.name}</div>
              <div className="route-goods">{route.goods}</div>
              <div className="route-desc">{route.desc}</div>
              <div className="route-meta">
                <span className="route-profit">+{route.profit - route.cost} dn</span>
                <span className="route-time">{Math.round(route.duration_ms / 1000)}s</span>
              </div>
              {!unlocked && (
                <span className="route-lock">
                  {state.den < route.unlock_den
                    ? `${route.unlock_den.toLocaleString()} dn required`
                    : `${route.unlock_aut} auctoritas required`}
                </span>
              )}
            </div>
          )
        })}
      </div>

      <div className="actions">
        <button
          className="btn btn-dispatch"
          onClick={handleDispatch}
          disabled={busy || !selectedRoute}
        >
          Dispatch galley
        </button>
        <button
          className="btn btn-otium"
          onClick={handleOtium}
          disabled={busy}
        >
          Take otium
        </button>
      </div>

      <p className="section-title">Merchant's journal</p>
      <div className="journal">
        {journal.length === 0 && (
          <div className="journal-entry">
            <div className="journal-date">Day 1 · Ostia</div>
            <div className="journal-text">
              The harbour smells of pitch and ambition. I have fifty denarii
              and a single battered ledger. The factor tells me the olive route
              to Capua is open. I shall begin there, as merchants have begun
              since the first ships crossed the Tyrrhenian.
            </div>
          </div>
        )}
        {journal.map((entry, i) => {
          const key = `${entry.day}-${i}`
          const isNew = newEntryKey && i === 0
          return (
            <div key={key} className={`journal-entry${isNew ? ' new' : ''}`}>
              <div className="journal-date">{entry.day}</div>
              <div className="journal-text">{entry.text}</div>
            </div>
          )
        })}
      </div>

      <div className="token-bar">
        Your save code: <span className="token-code">{state.token}</span>
        <button className="btn-new-game" onClick={handleNewGame}>
          New game
        </button>
      </div>
    </div>
  )
}
