import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Grid from './Grid'
import CluePanel from './CluePanel'
import ActiveClue from './ActiveClue'
import { useKeyboard } from '../hooks/useKeyboard'
import { useStore } from '../store'
import type { ClientPuzzle } from '../types'

interface Props {
  puzzleId: string
  showTimer: boolean
  showHints: boolean
}

function buildWordSpans(puzzle: ClientPuzzle) {
  const spans: { number: number; direction: 'across' | 'down'; cells: [number, number][] }[] = []
  for (const clue of puzzle.clues_across) {
    const key = Object.entries(puzzle.cell_numbers).find(([, n]) => n === clue.number)?.[0]
    if (!key) continue
    const [r, c] = key.split(',').map(Number)
    const cells: [number, number][] = []
    for (let j = c; j < puzzle.width && puzzle.cells[r][j] !== 'black'; j++) cells.push([r, j])
    spans.push({ number: clue.number, direction: 'across', cells })
  }
  for (const clue of puzzle.clues_down) {
    const key = Object.entries(puzzle.cell_numbers).find(([, n]) => n === clue.number)?.[0]
    if (!key) continue
    const [r, c] = key.split(',').map(Number)
    const cells: [number, number][] = []
    for (let i = r; i < puzzle.height && puzzle.cells[i][c] !== 'black'; i++) cells.push([i, c])
    spans.push({ number: clue.number, direction: 'down', cells })
  }
  return spans
}

function makeEmptyGrid(w: number, h: number) {
  return Array.from({ length: h }, () => Array(w).fill(''))
}

function makeStatusGrid(w: number, h: number) {
  return Array.from({ length: h }, () => Array(w).fill('default'))
}

export default function EmbedPlayer({ puzzleId, showTimer, showHints }: Props) {
  const { t } = useTranslation()
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const puzzle = useStore(s => s.puzzle)
  const solved = useStore(s => s.solved)
  const elapsed = useStore(s => s.elapsed)
  const startTime = useStore(s => s.startTime)
  const paused = useStore(s => s.paused)
  const tick = useStore(s => s.tick)
  useKeyboard()

  // timer
  useEffect(() => {
    if (!startTime || paused || !showTimer) return
    const id = setInterval(tick, 1000)
    return () => clearInterval(id)
  }, [startTime, paused, tick, showTimer])

  useEffect(() => {
    if (!puzzleId) {
      const t0 = setTimeout(() => { setError(t('embed.noPuzzleId')); setLoading(false) }, 0)
      return () => clearTimeout(t0)
    }

    fetch(`/api/puzzles/s/${puzzleId}`)
      .then(r => { if (!r.ok) throw new Error(t('embed.notFound')); return r.json() })
      .then(data => {
        // SAFETY: /api/puzzles/s/{id} always answers with the ClientPuzzle shape for existing ids
        const p = data.puzzle as ClientPuzzle
        const spans = buildWordSpans(p)
        useStore.setState({
          puzzleId: data.id,
          shortId: data.short_id,
          puzzle: p,
          entries: makeEmptyGrid(p.width, p.height),
          cellStatus: makeStatusGrid(p.width, p.height),
          selectedCell: null,
          direction: 'across',
          activeClue: null,
          wordSpans: spans,
          loading: false,
          startTime: Date.now(),
          elapsed: 0,
          paused: false,
          solved: false,
          hintsUsed: 0,
        })
        setLoading(false)
      })
      .catch(e => { setError(e.message); setLoading(false) })
  }, [puzzleId])

  // notify parent on completion
  useEffect(() => {
    if (solved && window.parent !== window) {
      window.parent.postMessage({ type: 'cruciverb:complete', elapsed }, '*')
    }
  }, [solved, elapsed])

  if (loading) return <div className="embed-loading"><div className="spinner" /></div>
  if (error) return <div className="embed-error">{error}</div>
  if (!puzzle) return null

  const mins = Math.floor(elapsed / 60)
  const secs = elapsed % 60

  return (
    <div className="embed-player">
      {solved && <div className="embed-solved">{t('embed.solved')}</div>}
      <div className="embed-header">
        <span className="embed-brand">{t('embed.brand')}</span>
        {showTimer && <span className="embed-timer">{mins}:{secs.toString().padStart(2, '0')}</span>}
      </div>
      <ActiveClue />
      <div className="embed-game">
        <div className="embed-grid">
          <Grid />
        </div>
        <CluePanel />
      </div>
      {showHints && !solved && (
        <div className="embed-hints">
          <button className="btn btn-sm" onClick={() => useStore.getState().checkCell()}>{t('game.check')}</button>
          <button className="btn btn-sm" onClick={() => useStore.getState().revealLetter()}>{t('game.reveal')}</button>
        </div>
      )}
    </div>
  )
}
