import { redis, redisConfigured } from '@/lib/redis';
import { logger } from '@/lib/logger';
import { enqueueJob } from '@/lib/queue/job-queue';

type VitalName = 'LCP' | 'FID' | 'CLS' | 'FCP' | 'TTFB' | 'INP';

export interface WebVitalSample {
  name: VitalName;
  value: number;
  rating?: string;
  url?: string;
  timestamp: string;
}

const MAX_SAMPLES_PER_VITAL = 200;
const SAMPLE_RATE = process.env.NODE_ENV === 'production' ? 0.25 : 1.0;

const ALERT_THRESHOLDS: Record<'LCP' | 'TTFB', { warn: number; critical: number }> = {
  LCP: { warn: 3000, critical: 4000 },
  TTFB: { warn: 1000, critical: 1500 },
};

function shouldSample(): boolean {
  return Math.random() < SAMPLE_RATE;
}

function computeStats(values: number[]) {
  if (values.length === 0) return { avg: 0, p90: 0, p95: 0 };
  const sorted = [...values].sort((a, b) => a - b);
  const avg = sorted.reduce((sum, val) => sum + val, 0) / sorted.length;
  const p90 = sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.9))];
  const p95 = sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))];
  return { avg, p90, p95 };
}

export async function storeWebVitalSample(sample: WebVitalSample): Promise<{
  alertLevel?: 'warning' | 'critical';
  stats?: { avg: number; p90: number; p95: number };
}> {
  if (!redisConfigured) return {};
  if (!shouldSample()) return {};

  try {
    const key = `webvitals:${sample.name}`;
    await redis.lpush(key, JSON.stringify(sample));
    await redis.ltrim(key, 0, MAX_SAMPLES_PER_VITAL - 1);

    if (sample.name === 'LCP' || sample.name === 'TTFB') {
      const recent = await redis.lrange(key, 0, 49);
      const values = recent
        .map(entry => {
          try {
            return JSON.parse(entry)?.value as number;
          } catch {
            return null;
          }
        })
        .filter((v): v is number => typeof v === 'number');

      const stats = computeStats(values);
      const threshold = ALERT_THRESHOLDS[sample.name];

      if (stats.p95 >= threshold.critical) {
        await enqueueJob('web_vitals_alert', {
          vitalName: sample.name,
          alertLevel: 'critical',
          currentP90: stats.p95,
          threshold: threshold.critical,
          sampleCount: values.length,
        });
        return { alertLevel: 'critical', stats };
      }
      if (stats.p95 >= threshold.warn) {
        await enqueueJob('web_vitals_alert', {
          vitalName: sample.name,
          alertLevel: 'warning',
          currentP90: stats.p95,
          threshold: threshold.warn,
          sampleCount: values.length,
        });
        return { alertLevel: 'warning', stats };
      }
    }
  } catch (error) {
    logger.warn('Failed to store web vitals sample', { error: error instanceof Error ? error.message : String(error) });
  }

  return {};
}

/**
 * Get comprehensive stats for all web vitals
 */
export async function getWebVitalsStats(): Promise<{
  vitals: Array<{
    name: VitalName;
    sampleCount: number;
    avg: number;
    p90: number;
    p95: number;
    min: number;
    max: number;
    alertLevel: 'ok' | 'warning' | 'critical';
    lastUpdated: string | null;
  }>;
  lastFetch: string;
}> {
  if (!redisConfigured) {
    return {
      vitals: [],
      lastFetch: new Date().toISOString(),
    };
  }

  const vitalNames: VitalName[] = ['LCP', 'FID', 'CLS', 'FCP', 'TTFB', 'INP'];
  const results = await Promise.all(
    vitalNames.map(async (name) => {
      const key = `webvitals:${name}`;
      const raw = await redis.lrange(key, 0, -1);

      const samples = raw
        .map((entry) => {
          try {
            return JSON.parse(entry) as WebVitalSample;
          } catch {
            return null;
          }
        })
        .filter((s): s is WebVitalSample => s !== null);

      const values = samples.map((s) => s.value);
      const stats = computeStats(values);
      const lastSample = samples.length > 0 ? samples[0] : null;

      // Determine alert level
      let alertLevel: 'ok' | 'warning' | 'critical' = 'ok';
      if (name === 'LCP' || name === 'TTFB') {
        const threshold = ALERT_THRESHOLDS[name];
        if (stats.p95 >= threshold.critical) {
          alertLevel = 'critical';
        } else if (stats.p95 >= threshold.warn) {
          alertLevel = 'warning';
        }
      }

      return {
        name,
        sampleCount: samples.length,
        ...stats,
        min: values.length > 0 ? Math.min(...values) : 0,
        max: values.length > 0 ? Math.max(...values) : 0,
        alertLevel,
        lastUpdated: lastSample?.timestamp ?? null,
      };
    })
  );

  return {
    vitals: results,
    lastFetch: new Date().toISOString(),
  };
}

/**
 * Get recent samples for a specific vital
 */
export async function getRecentSamples(
  vitalName: VitalName,
  limit = 50
): Promise<WebVitalSample[]> {
  if (!redisConfigured) return [];

  const key = `webvitals:${vitalName}`;
  const raw = await redis.lrange(key, 0, limit - 1);

  return raw
    .map((entry) => {
      try {
        return JSON.parse(entry) as WebVitalSample;
      } catch {
        return null;
      }
    })
    .filter((s): s is WebVitalSample => s !== null);
}

/**
 * Clear all web vitals samples (for testing)
 */
export async function clearWebVitalsSamples(): Promise<void> {
  if (!redisConfigured) return;

  const vitalNames: VitalName[] = ['LCP', 'FID', 'CLS', 'FCP', 'TTFB', 'INP'];
  await Promise.all(
    vitalNames.map((name) => redis.del(`webvitals:${name}`))
  );
}
