'use client'

import * as React from 'react'
import { motion, useReducedMotion } from 'framer-motion'
import { cn } from '@/lib/utils'

/**
 * useMounted — returns true after the component has hydrated on the client.
 * Used to gate Framer Motion animations that would otherwise cause SSR/client
 * hydration mismatches.
 */
function useMounted() {
  const [mounted, setMounted] = React.useState(false)
  React.useEffect(() => {
    setMounted(true)
  }, [])
  return mounted
}

/**
 * Round a number to 3 decimal places and return as a string.
 *
 * Used for SVG geometry attributes computed with Math.sin / Math.cos /
 * Math.PI. Different JS engines can produce results that differ in the
 * 17th significant digit, which React serializes differently on SSR vs
 * client, triggering hydration mismatch warnings.
 */
function round3(n: number): string {
  return n.toFixed(3)
}

/**
 * Animated molecular structure background.
 * Renders an SVG with floating molecule nodes and connecting bonds.
 *
 * Before mount (SSR + first client render), renders plain static circles
 * so the DOM is identical on both sides. After mount, switches to
 * animated motion.circle elements.
 */
export function MoleculeBackground({
  className,
  density = 'normal',
}: {
  className?: string
  density?: 'sparse' | 'normal' | 'dense'
}) {
  const reduce = useReducedMotion()
  const mounted = useMounted()
  const count = density === 'sparse' ? 8 : density === 'dense' ? 18 : 12

  const nodes = React.useMemo(
    () =>
      Array.from({ length: count }, (_, i) => {
        const xNum = 10 + ((i * 73) % 90)
        const yNum = 10 + ((i * 47) % 80)
        const rNum = 3 + ((i * 13) % 5)
        return {
          id: i,
          xNum,
          yNum,
          rNum,
          x: round3(xNum),
          y: round3(yNum),
          rGlow: round3(rNum * 0.4),
          rCore: round3(rNum * 0.18),
          yShift: round3(yNum - 1.5),
          delay: (i % 6) * 0.6,
        }
      }),
    [count]
  )

  const bonds = React.useMemo(() => {
    const out: [number, number][] = []
    for (let i = 0; i < nodes.length; i++) {
      for (let j = i + 1; j < nodes.length; j++) {
        const a = nodes[i]
        const b = nodes[j]
        const d = Math.hypot(a.xNum - b.xNum, a.yNum - b.yNum)
        if (d < 28) out.push([i, j])
      }
    }
    return out
  }, [nodes])

  const shouldAnimate = mounted && !reduce

  return (
    <svg
      className={cn('pointer-events-none absolute inset-0 h-full w-full', className)}
      viewBox="0 0 100 100"
      preserveAspectRatio="xMidYMid slice"
      role="presentation"
      aria-hidden="true"
    >
      <defs>
        <radialGradient id="molGlow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#8fb9ad" stopOpacity="0.9" />
          <stop offset="100%" stopColor="#8fb9ad" stopOpacity="0" />
        </radialGradient>
      </defs>
      {bonds.map(([i, j], k) => (
        <line
          key={`bond-${k}`}
          x1={nodes[i].x}
          y1={nodes[i].y}
          x2={nodes[j].x}
          y2={nodes[j].y}
          stroke="rgba(143, 185, 173, 0.18)"
          strokeWidth="0.15"
        />
      ))}
      {nodes.map((n) =>
        shouldAnimate ? (
          <motion.circle
            key={`node-${n.id}`}
            cx={n.x}
            cy={n.y}
            r={n.rGlow}
            fill="url(#molGlow)"
            initial={{ opacity: 0.3 }}
            animate={{ opacity: [0.3, 0.9, 0.3], cy: [n.y, n.yShift, n.y] }}
            transition={{
              duration: 5 + n.delay,
              repeat: Infinity,
              ease: 'easeInOut',
              delay: n.delay,
            }}
          />
        ) : (
          <circle
            key={`node-${n.id}`}
            cx={n.x}
            cy={n.y}
            r={n.rGlow}
            fill="url(#molGlow)"
            opacity="0.6"
          />
        )
      )}
      {nodes.map((n) => (
        <circle
          key={`core-${n.id}`}
          cx={n.x}
          cy={n.y}
          r={n.rCore}
          fill="#bdd4cd"
          opacity="0.7"
        />
      ))}
    </svg>
  )
}

/**
 * Animated DNA double-helix SVG.
 *
 * Before mount, renders static paths/lines. After mount, switches to
 * animated motion elements.
 */
export function DNAHelix({ className }: { className?: string }) {
  const reduce = useReducedMotion()
  const mounted = useMounted()
  const rungs = React.useMemo(() => Array.from({ length: 16 }, (_, i) => i), [])
  const shouldAnimate = mounted && !reduce

  return (
    <svg
      className={cn('pointer-events-none', className)}
      viewBox="0 0 120 360"
      fill="none"
      role="presentation"
      aria-hidden="true"
    >
      <defs>
        <linearGradient id="dnaA" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#8fb9ad" />
          <stop offset="100%" stopColor="#0d5d50" />
        </linearGradient>
        <linearGradient id="dnaB" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#bdd4cd" />
          <stop offset="100%" stopColor="#6f9f91" />
        </linearGradient>
      </defs>
      {shouldAnimate ? (
        <>
          <motion.path
            d="M30 0 C 90 60, 30 120, 90 180 C 30 240, 90 300, 30 360"
            stroke="url(#dnaA)"
            strokeWidth="2.5"
            fill="none"
            initial={{ pathLength: 0 }}
            animate={{ pathLength: 1 }}
            transition={{ duration: 2.2, ease: 'easeInOut' }}
          />
          <motion.path
            d="M90 0 C 30 60, 90 120, 30 180 C 90 240, 30 300, 90 360"
            stroke="url(#dnaB)"
            strokeWidth="2.5"
            fill="none"
            initial={{ pathLength: 0 }}
            animate={{ pathLength: 1 }}
            transition={{ duration: 2.2, ease: 'easeInOut', delay: 0.3 }}
          />
          {rungs.map((i) => {
            const y = 12 + i * 22
            const t = (i / 15) * Math.PI * 2
            const x1 = round3(60 + Math.sin(t) * 30)
            const x2 = round3(60 - Math.sin(t) * 30)
            return (
              <motion.line
                key={i}
                x1={x1}
                y1={y}
                x2={x2}
                y2={y}
                stroke="rgba(143, 185, 173, 0.55)"
                strokeWidth="1.5"
                initial={{ opacity: 0 }}
                animate={{ opacity: [0, 0.7, 0] }}
                transition={{ duration: 3, repeat: Infinity, delay: i * 0.18 }}
              />
            )
          })}
        </>
      ) : (
        <>
          {/* Static fallback rendered on SSR and first client render */}
          <path
            d="M30 0 C 90 60, 30 120, 90 180 C 30 240, 90 300, 30 360"
            stroke="url(#dnaA)"
            strokeWidth="2.5"
            fill="none"
          />
          <path
            d="M90 0 C 30 60, 90 120, 30 180 C 90 240, 30 300, 90 360"
            stroke="url(#dnaB)"
            strokeWidth="2.5"
            fill="none"
          />
          {rungs.map((i) => {
            const y = 12 + i * 22
            const t = (i / 15) * Math.PI * 2
            const x1 = round3(60 + Math.sin(t) * 30)
            const x2 = round3(60 - Math.sin(t) * 30)
            return (
              <line
                key={i}
                x1={x1}
                y1={y}
                x2={x2}
                y2={y}
                stroke="rgba(143, 185, 173, 0.55)"
                strokeWidth="1.5"
                opacity="0.35"
              />
            )
          })}
        </>
      )}
    </svg>
  )
}

/**
 * Slowly rotating orbital rings — used as decorative background motif.
 */
export function OrbitalRings({ className }: { className?: string }) {
  const reduce = useReducedMotion()
  const mounted = useMounted()
  const shouldAnimate = mounted && !reduce
  return (
    <div className={cn('pointer-events-none absolute inset-0 overflow-hidden', className)}>
      <div
        className={cn(
          'absolute left-1/2 top-1/2 h-[600px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-white/10',
          shouldAnimate && 'animate-spin-slow'
        )}
      />
      <div
        className={cn(
          'absolute left-1/2 top-1/2 h-[900px] w-[900px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-white/5',
          shouldAnimate && 'animate-spin-slow'
        )}
        style={shouldAnimate ? { animationDirection: 'reverse', animationDuration: '60s' } : undefined}
      />
      <div className="absolute left-1/2 top-1/2 h-[300px] w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-full border border-[#8fb9ad]/20" />
    </div>
  )
}
