// Sparkles — restrained particle field for hero / opener backdrops.
//
// Design goals:
//   - Professional, NOT playful. No rainbow, no big glittery stars,
//     no chaotic motion. Tiny brand-tinted dots that fade in and out
//     out of phase — reads as "atmosphere", not "Christmas tree".
//   - SSR-safe: positions / sizes / delays derive deterministically
//     from the index, so server-rendered HTML matches the first
//     client render (no hydration mismatch, no re-shuffle on each
//     render).
//   - Pointer-events off, aria-hidden — purely decorative.
//   - Respects prefers-reduced-motion: the `motion-safe:` variant on
//     the twinkle animation means each dot freezes at opacity 0 when
//     the user has reduced motion enabled.
//
// Drop this absolute-fill inside any container (hero, section, card)
// and it covers the parent. Tune via `count`, `tone`, `intensity`.

import type { ReactNode } from 'react'
import { cn } from '../cn'

interface SparklesProps {
  /** How many dots to render. Default 22. Sweet spot is 16–28 —
   *  fewer feels accidental, more starts to feel busy. */
  readonly count?: number
  /** Brand mode. Cool = violet/cyan accents (default); warm = amber/rose. */
  readonly tone?: 'cool' | 'warm'
  /** Density tier. `'subtle'` is the default and what most heros want;
   *  `'normal'` bumps the max-opacity peak a bit; `'strong'` makes
   *  the field more obvious. Each tier still respects the
   *  "professional, not playful" budget. */
  readonly intensity?: 'subtle' | 'normal' | 'strong'
  readonly className?: string
}

// Two prime-ish multipliers per axis. Spreads positions evenly across
// the container without lining up on a grid. Picked by eye — change
// only if you want a different distribution.
const FREQ_X = 137.5
const FREQ_Y = 73.13

const INTENSITY_OPACITY: Record<NonNullable<SparklesProps['intensity']>, string> = {
  subtle: 'opacity-50',
  normal: 'opacity-75',
  strong: 'opacity-100',
}

export const Sparkles = ({
  count = 22, tone = 'cool', intensity = 'subtle', className,
}: SparklesProps): ReactNode => {
  // Dot CORE is near-white so it pops against the brand-tinted
  // MeshBackdrop blobs (those use the same violet/cyan and would
  // swallow same-coloured dots). The HALO is brand-tinted — that's
  // what visually anchors the sparkle to the rest of the palette
  // without coloring the dot itself.
  const haloColors = tone === 'warm'
    ? ['oklch(0.78 0.16 60)', 'oklch(0.72 0.18 25)']
    : ['oklch(0.78 0.18 290)', 'oklch(0.74 0.16 220)']

  return (
    <div
      aria-hidden="true"
      className={cn(
        'absolute inset-0 overflow-hidden pointer-events-none',
        INTENSITY_OPACITY[intensity],
        className,
      )}
    >
      {Array.from({ length: count }, (_, i) => {
        // Deterministic pseudo-random spread — golden-ratio-ish step
        // around 0..100% per axis.
        const x = (i * FREQ_X) % 100
        const y = (i * FREQ_Y) % 100
        // 2-4px diameter — small enough to read as a particle, not as
        // a hit-target.
        const size = 2 + (i % 3)
        // Stagger the twinkle so the field never blinks in unison.
        const delay = (i * 0.42) % 6
        const halo = haloColors[i % haloColors.length]!
        return (
          <span
            key={i}
            className="absolute rounded-full motion-safe:animate-twinkle"
            style={{
              left: `${x}%`,
              top: `${y}%`,
              width: `${size}px`,
              height: `${size}px`,
              // Near-white core gives the dot contrast against any
              // backdrop colour — that's what makes it actually read
              // as a sparkle and not vanish into the mesh blobs.
              backgroundColor: 'oklch(0.98 0 0)',
              // Two-stop halo: tight bright ring at 1× size, soft
              // brand-tinted bloom at 4× size. The double shadow is
              // what gives sparkles their characteristic "spark"
              // glow vs a flat dot with a single blur.
              boxShadow: `0 0 ${size}px oklch(0.98 0 0), 0 0 ${size * 4}px ${halo}`,
              animationDelay: `${delay}s`,
            }}
          />
        )
      })}
    </div>
  )
}
