import { useEffect, useRef } from 'react'
// Light build: drops the eval-based expression engine (smaller bundle, no eval
// warning). Plenty for a looping mascot; swap to 'lottie-web' only if an asset
// genuinely needs After Effects expressions.
import lottie, { type AnimationItem } from 'lottie-web/build/player/lottie_light'

interface Props {
  // Parsed Lottie JSON (imported, so it bundles offline). When undefined the
  // `fallback` is rendered instead — letting the companion ship before any
  // animation asset exists.
  animationData?: object
  loop?: boolean
  className?: string
  // Mirror the animation left↔right (for assets drawn facing the wrong way).
  flip?: boolean
  fallback: React.ReactNode
}

// Tighten the SVG viewBox to the animation's actual drawn content so an asset
// with a lot of empty artboard padding (common with stock Lottie files) fills
// the badge instead of floating tiny in the middle. We union the content bbox
// across a few frames (the mascot moves) and make it square so it isn't
// distorted by the square container.
function fitToContent(anim: AnimationItem, svg: SVGSVGElement) {
  try {
    const frames = anim.getDuration(true)
    let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity
    const SAMPLES = 6
    for (let i = 0; i < SAMPLES; i++) {
      anim.goToAndStop(Math.floor(((frames - 1) * i) / (SAMPLES - 1)), true)
      const b = svg.getBBox()
      if (b.width === 0 || b.height === 0) continue
      x1 = Math.min(x1, b.x)
      y1 = Math.min(y1, b.y)
      x2 = Math.max(x2, b.x + b.width)
      y2 = Math.max(y2, b.y + b.height)
    }
    if (!isFinite(x1)) return
    const cx = (x1 + x2) / 2, cy = (y1 + y2) / 2
    const side = Math.max(x2 - x1, y2 - y1) * 1.14 // ~7% breathing room each side
    svg.setAttribute('viewBox', `${cx - side / 2} ${cy - side / 2} ${side} ${side}`)
    svg.setAttribute('preserveAspectRatio', 'xMidYMid meet')
  } catch {
    /* getBBox unsupported / not laid out — leave the original viewBox */
  } finally {
    anim.goToAndPlay(0, true)
  }
}

// A thin wrapper over lottie-web (framework-agnostic, no React peer deps, fully
// offline). Reloads the animation whenever the data changes — moods swap by
// passing a different `animationData`.
export function LottiePlayer({ animationData, loop = true, className, flip, fallback }: Props) {
  const ref = useRef<HTMLDivElement>(null)
  const anim = useRef<AnimationItem | null>(null)

  useEffect(() => {
    const container = ref.current
    if (!container || !animationData) return
    const item = lottie.loadAnimation({
      container,
      renderer: 'svg',
      loop,
      autoplay: true,
      animationData,
    })
    anim.current = item
    item.addEventListener('DOMLoaded', () => {
      const svg = container.querySelector('svg')
      if (svg) fitToContent(item, svg as SVGSVGElement)
    })
    return () => {
      item.destroy()
      anim.current = null
    }
  }, [animationData, loop])

  if (!animationData) return <>{fallback}</>
  return (
    <div
      ref={ref}
      className={className}
      style={flip ? { transform: 'scaleX(-1)' } : undefined}
      aria-hidden
    />
  )
}
