import { useEffect, useRef, useState } from 'react'
import { IconChartBar, IconCpu, IconDatabase, IconRobot, IconServer } from '@tabler/icons-react'
import CircularGauge from '~/components/systeminfo/CircularGauge'
import StyledButton from '~/components/StyledButton'
import BenchmarkResult from '#models/benchmark_result'

interface ScoreRevealProps {
  result: BenchmarkResult
  scoreScale?: { max: number; caption: string }
  onDone: () => void
}

// Same thresholds as the NOMAD Score section on the benchmark page.
const getScoreColor = (score: number) => {
  if (score >= 70) return 'text-green-600'
  if (score >= 40) return 'text-yellow-600'
  return 'text-red-600'
}

// AI tokens/sec normalized to 0-100 (30 tok/s = 50, 60 tok/s = 100),
// mirroring the benchmark page's getAIScore.
const getAIScore = (tokensPerSecond: number): number =>
  Math.min(100, Math.max(0, (tokensPerSecond / 60) * 100))

/** rAF count-up from 0 to `target` with ease-out, for the big score number. */
function useCountUp(target: number, durationMs = 1200): number {
  const [value, setValue] = useState(0)
  useEffect(() => {
    let raf = 0
    const start = performance.now()
    const tick = (now: number) => {
      const t = Math.min(1, (now - start) / durationMs)
      const eased = 1 - Math.pow(1 - t, 3)
      setValue(target * eased)
      if (t < 1) raf = requestAnimationFrame(tick)
    }
    raf = requestAnimationFrame(tick)
    return () => cancelAnimationFrame(raf)
  }, [target, durationMs])
  return value
}

/**
 * End-of-run score reveal. Replaces the abrupt unmount of the live run view
 * with a deliberate report: big NOMAD score gauge + count-up number, then the
 * sub-score gauges cascading in. Dismisses via the Continue button or an
 * auto-dismiss timer.
 */
export default function ScoreReveal({
  result,
  scoreScale = { max: 100, caption: 'out of 100' },
  onDone,
}: ScoreRevealProps) {
  const displayScore = useCountUp(result.nomad_score)

  // Sub-score gauges, mirroring the System Performance / AI Performance grids.
  const gauges: {
    label: string
    value: number
    variant: 'cpu' | 'memory' | 'disk'
    icon: React.ReactNode
  }[] = [
    { label: 'CPU', value: result.cpu_score * 100, variant: 'cpu', icon: <IconCpu className="w-6 h-6" /> },
    { label: 'Memory', value: result.memory_score * 100, variant: 'memory', icon: <IconDatabase className="w-6 h-6" /> },
    { label: 'Disk Read', value: result.disk_read_score * 100, variant: 'disk', icon: <IconServer className="w-6 h-6" /> },
    { label: 'Disk Write', value: result.disk_write_score * 100, variant: 'disk', icon: <IconServer className="w-6 h-6" /> },
  ]
  if (result.ai_tokens_per_second) {
    gauges.push({
      label: 'AI Score',
      value: getAIScore(result.ai_tokens_per_second),
      variant: 'cpu',
      icon: <IconRobot className="w-6 h-6" />,
    })
  }

  // Cascade: mount one gauge every 150ms; each CircularGauge animates 0→value
  // on mount, so staggered mounts produce the cascade.
  const [visibleCount, setVisibleCount] = useState(0)
  useEffect(() => {
    if (visibleCount >= gauges.length) return
    const id = setTimeout(() => setVisibleCount((n) => n + 1), 150)
    return () => clearTimeout(id)
  }, [visibleCount, gauges.length])

  // Dismiss exactly once, whether via the button or the auto-dismiss timer.
  const doneRef = useRef(false)
  const onDoneRef = useRef(onDone)
  onDoneRef.current = onDone
  const fireDone = () => {
    if (doneRef.current) return
    doneRef.current = true
    onDoneRef.current()
  }
  useEffect(() => {
    const id = setTimeout(fireDone, 5000)
    return () => clearTimeout(id)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  return (
    <div className="space-y-6">
      <div className="bg-desert-white rounded-lg border border-desert-stone-light overflow-hidden">
        <div className="bg-desert-olive px-6 py-2 flex items-center gap-2">
          <div className="w-1 h-4 bg-desert-green" />
          <span className="text-xs font-semibold text-white uppercase tracking-wide">Report</span>
        </div>

        <div className="p-8">
          <div className="flex flex-col md:flex-row items-center gap-8">
            <div className="shrink-0">
              <CircularGauge
                value={Math.min(100, (result.nomad_score / scoreScale.max) * 100)}
                label="NOMAD Score"
                size="lg"
                variant="cpu"
                subtext={scoreScale.caption}
                icon={<IconChartBar className="w-8 h-8" />}
              />
            </div>
            <div className="flex-1 space-y-4">
              <div
                className={`text-5xl font-bold font-mono tabular-nums ${getScoreColor(result.nomad_score)}`}
              >
                {displayScore.toFixed(1)}
              </div>
              <p className="text-desert-stone-dark">
                Your NOMAD Score is a weighted composite of all benchmark results.
              </p>
            </div>
          </div>

          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6 mt-8">
            {gauges.slice(0, visibleCount).map((g) => (
              <div
                key={g.label}
                className="bg-desert-white rounded-lg p-4 border border-desert-stone-light"
              >
                <CircularGauge value={g.value} label={g.label} size="md" variant={g.variant} icon={g.icon} />
              </div>
            ))}
          </div>

          <div className="mt-8 flex justify-end">
            <StyledButton onClick={fireDone} icon="IconArrowRight">
              Continue
            </StyledButton>
          </div>
        </div>
      </div>
    </div>
  )
}
