import { useEffect } from 'react'
import type { Metric } from 'web-vitals'

type MetricName = 'LCP' | 'INP' | 'CLS' | 'FCP' | 'TTFB'

export interface ReportedMetric {
  name: MetricName
  value: number
  rating: string
  route: string
}

export interface VitalsReporter {
  report(metric: ReportedMetric): void
}

export interface WebVitalsBeaconProps {
  reporter: VitalsReporter
}

let hasRegisteredVitals = false

function currentRoute(): string {
  if (typeof window === 'undefined') {
    return '/'
  }

  return `${window.location.pathname}${window.location.search}${window.location.hash}`
}

function createMetricReporter(reporter: VitalsReporter, route: string) {
  return (metric: Metric): void => {
    reporter.report({
      name: metric.name as MetricName,
      value: metric.value,
      rating: metric.rating,
      route,
    })
  }
}

export async function reportWebVitals(reporter: VitalsReporter): Promise<void> {
  const route = currentRoute()
  const send = createMetricReporter(reporter, route)
  const { onCLS, onFCP, onINP, onLCP, onTTFB } = await import('web-vitals')

  onCLS(send)
  onFCP(send)
  onINP(send)
  onLCP(send)
  onTTFB(send)
}

export function WebVitalsBeacon({ reporter }: WebVitalsBeaconProps): null {
  useEffect(() => {
    if (hasRegisteredVitals) {
      return
    }

    hasRegisteredVitals = true
    void reportWebVitals(reporter)
  }, [reporter])

  return null
}
