/**
 * Web Vitals monitoring for frontend performance.
 *
 * Captures Core Web Vitals (LCP, FID, CLS) and sends to analytics.
 * These metrics are critical for user experience and SEO.
 *
 * @see Story 1.8 - T8.4: Web Vitals (FCP, LCP, TTI)
 */

import { onCLS, onFCP, onINP, onLCP, onTTFB, type Metric } from 'web-vitals';

type VitalsReporter = (metric: VitalMetric) => void;

export interface VitalMetric {
	name: 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB';
	value: number;
	rating: 'good' | 'needs-improvement' | 'poor';
	delta: number;
	id: string;
}

/**
 * Web Vitals thresholds (Core Web Vitals 2024 standards).
 *
 * - LCP (Largest Contentful Paint): < 2.5s good, < 4s needs improvement
 * - FCP (First Contentful Paint): < 1.8s good, < 3s needs improvement
 * - INP (Interaction to Next Paint): < 200ms good, < 500ms needs improvement
 * - CLS (Cumulative Layout Shift): < 0.1 good, < 0.25 needs improvement
 * - TTFB (Time to First Byte): < 800ms good, < 1.8s needs improvement
 */
const THRESHOLDS = {
	LCP: { good: 2500, needsImprovement: 4000 },
	FCP: { good: 1800, needsImprovement: 3000 },
	INP: { good: 200, needsImprovement: 500 },
	CLS: { good: 0.1, needsImprovement: 0.25 },
	TTFB: { good: 800, needsImprovement: 1800 }
} as const;

function getRating(
	name: VitalMetric['name'],
	value: number
): 'good' | 'needs-improvement' | 'poor' {
	const threshold = THRESHOLDS[name];
	if (value <= threshold.good) return 'good';
	if (value <= threshold.needsImprovement) return 'needs-improvement';
	return 'poor';
}

function createVitalMetric(metric: Metric): VitalMetric {
	return {
		name: metric.name as VitalMetric['name'],
		value: metric.value,
		rating: getRating(metric.name as VitalMetric['name'], metric.value),
		delta: metric.delta,
		id: metric.id
	};
}

/**
 * Initialize Web Vitals collection.
 *
 * @param reporter - Callback function to report metrics (e.g., to analytics)
 */
export function initWebVitals(reporter: VitalsReporter): void {
	// Core Web Vitals
	onLCP((metric) => reporter(createVitalMetric(metric)));
	onCLS((metric) => reporter(createVitalMetric(metric)));
	onINP((metric) => reporter(createVitalMetric(metric)));

	// Other Web Vitals
	onFCP((metric) => reporter(createVitalMetric(metric)));
	onTTFB((metric) => reporter(createVitalMetric(metric)));
}

/**
 * Default reporter that logs to console (dev) or sends to backend (prod).
 */
export function createDefaultReporter(options: {
	endpoint?: string;
	debug?: boolean;
}): VitalsReporter {
	return (metric: VitalMetric) => {
		// Log in development
		if (options.debug) {
			// eslint-disable-next-line no-console
			console.log(`[WebVitals] ${metric.name}: ${metric.value.toFixed(2)} (${metric.rating})`);
		}

		// Send to analytics endpoint in production
		if (options.endpoint) {
			// Use sendBeacon for reliability during page unload
			const body = JSON.stringify({
				metric: metric.name,
				value: metric.value,
				rating: metric.rating,
				delta: metric.delta,
				id: metric.id,
				timestamp: Date.now(),
				url: window.location.href
			});

			if (navigator.sendBeacon) {
				navigator.sendBeacon(options.endpoint, body);
			} else {
				fetch(options.endpoint, {
					method: 'POST',
					body,
					headers: { 'Content-Type': 'application/json' },
					keepalive: true
				}).catch(() => {
					// Silently fail - vitals are best-effort
				});
			}
		}
	};
}
