import React, { useEffect, useState, useMemo } from 'react'
import { Box, Text, type Color } from '@anthropic/ink'
import type { AnimMode } from '../types'
import { renderAnimatedSprite, flipSpriteLines, getIdleAnimMode, getPetOverlay } from '../sprites/renderer'

/** Vertical padding — bounce shifts within this space */
const V_PAD = 4

interface SpriteAnimatorProps {
  /** Base sprite lines (ANSI is preserved) */
  lines: string[]
  /** Text color for the sprite */
  color?: Color
  /** Tick interval in ms (default 250) */
  tickMs?: number
  /** Single mode; omit for idle auto-play */
  mode?: AnimMode
  /** Center horizontally (default true) */
  centered?: boolean
  /** Show pet hearts overlay */
  petting?: boolean
  /** Flip horizontally (for player Pokemon facing opponent) */
  flip?: boolean
}

/**
 * Animated sprite renderer with built-in tick loop.
 *
 * - Keeps ANSI intact (parse → pixel grid → transform → render)
 * - Pads vertically so bounce never shifts layout
 * - Grid transforms guarantee fixed output height
 */
export function SpriteAnimator({
  lines,
  color,
  tickMs = 100,
  mode,
  centered = true,
  petting,
  flip,
}: SpriteAnimatorProps) {
  const [tick, setTick] = useState(0)

  useEffect(() => {
    const timer = setInterval(() => setTick(t => t + 1), tickMs)
    return () => clearInterval(timer)
  }, [tickMs])

  // Flip sprite if needed (cached)
  const sourceLines = useMemo(
    () => flip ? flipSpriteLines(lines) : lines,
    [lines, flip],
  )

  // Add vertical padding — bounce shifts within this space
  const padded = [...Array(V_PAD).fill(''), ...sourceLines, ...Array(V_PAD).fill('')]

  // Apply animation (renderer parses to pixels, transforms, renders back)
  const currentMode = mode ?? getIdleAnimMode(tick)
  const animated = renderAnimatedSprite(padded, tick, currentMode)

  // Pet hearts overlay
  const overlay = petting ? getPetOverlay(tick) : null
  const displayLines = overlay ? [...overlay, ...animated] : animated

  const spriteBlock = (
    <Box flexDirection="column">
      {displayLines.map((line, i) => (
        <Text key={i} color={color}>{line || ' '}</Text>
      ))}
    </Box>
  )

  if (!centered) return spriteBlock

  return (
    <Box flexDirection="row" justifyContent="center" width="100%">
      {spriteBlock}
    </Box>
  )
}
