import { useEffect, useCallback } from 'react';

export interface WebVitalMetric {
    name: 'CLS' | 'LCP' | 'FID' | 'FCP' | 'TTFB';
    value: number;
    rating: 'good' | 'needs-improvement' | 'poor';
}

const RATINGS: Record<WebVitalMetric['name'], [number, number]> = {
    CLS: [0.1, 0.25],
    LCP: [2500, 4000],
    FID: [100, 300],
    FCP: [1800, 3000],
    TTFB: [800, 1800],
};

export function getRating(name: WebVitalMetric['name'], value: number): WebVitalMetric['rating'] {
    const [good, poor] = RATINGS[name];
    if (value <= good) return 'good';
    if (value <= poor) return 'needs-improvement';
    return 'poor';
}

export function useWebVitals(onMetric?: (metric: WebVitalMetric) => void): void {
    const handleMetric = useCallback(
        (name: WebVitalMetric['name'], value: number) => {
            if (onMetric) {
                onMetric({ name, value, rating: getRating(name, value) });
            }
        },
        [onMetric],
    );

    useEffect(() => {
        // SSR safety guard
        if (typeof window === 'undefined' || typeof PerformanceObserver === 'undefined') {
            return;
        }

        const observers: PerformanceObserver[] = [];

        // LCP
        try {
            const lcpObserver = new PerformanceObserver((list) => {
                const entries = list.getEntries();
                const lastEntry = entries[entries.length - 1] as PerformanceEntry & { startTime: number };
                handleMetric('LCP', lastEntry.startTime);
            });
            lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
            observers.push(lcpObserver);
        } catch {
            // LCP not supported in this environment
        }

        // FID
        try {
            const fidObserver = new PerformanceObserver((list) => {
                const entries = list.getEntries() as (PerformanceEntry & {
                    processingStart: number;
                    startTime: number;
                })[];
                entries.forEach((entry) => {
                    handleMetric('FID', entry.processingStart - entry.startTime);
                });
            });
            fidObserver.observe({ type: 'first-input', buffered: true });
            observers.push(fidObserver);
        } catch {
            // FID not supported in this environment
        }

        // CLS
        let clsValue = 0;
        try {
            const clsObserver = new PerformanceObserver((list) => {
                const entries = list.getEntries() as (PerformanceEntry & {
                    hadRecentInput: boolean;
                    value: number;
                })[];
                entries.forEach((entry) => {
                    if (!entry.hadRecentInput) {
                        clsValue += entry.value;
                        handleMetric('CLS', clsValue);
                    }
                });
            });
            clsObserver.observe({ type: 'layout-shift', buffered: true });
            observers.push(clsObserver);
        } catch {
            // CLS not supported in this environment
        }

        // FCP & TTFB via paint + navigation entries (one-time reads, not observer)
        try {
            const paintEntries = performance.getEntriesByType('paint') as PerformanceEntry[];
            paintEntries.forEach((entry) => {
                if (entry.name === 'first-contentful-paint') {
                    handleMetric('FCP', entry.startTime);
                }
            });

            const navEntries = performance.getEntriesByType('navigation') as (PerformanceEntry & {
                responseStart: number;
                requestStart: number;
            })[];
            if (navEntries.length > 0) {
                handleMetric('TTFB', navEntries[0].responseStart - navEntries[0].requestStart);
            }
        } catch {
            // Paint/navigation entries not supported in this environment
        }

        return () => {
            observers.forEach((observer) => observer.disconnect());
        };
    }, [handleMetric]);
}
