import { useEffect, useCallback } from 'react';
import { useLocation } from 'react-router-dom';

// Analytics event types
interface AnalyticsEvent {
  type: 'pageview' | 'feature_usage' | 'performance' | 'error';
  timestamp: number;
  data: Record<string, unknown>;
}

// Simple in-memory analytics storage
const ANALYTICS_KEY = 'mockupaws_analytics';
const MAX_EVENTS = 1000;

class AnalyticsService {
  private events: AnalyticsEvent[] = [];
  private userId: string | null = null;
  private sessionId: string;

  constructor() {
    this.sessionId = this.generateSessionId();
    this.loadEvents();
    this.trackSessionStart();
  }

  private generateSessionId(): string {
    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  private loadEvents() {
    try {
      const stored = localStorage.getItem(ANALYTICS_KEY);
      if (stored) {
        this.events = JSON.parse(stored);
      }
    } catch {
      this.events = [];
    }
  }

  private saveEvents() {
    try {
      // Keep only recent events
      const recentEvents = this.events.slice(-MAX_EVENTS);
      localStorage.setItem(ANALYTICS_KEY, JSON.stringify(recentEvents));
    } catch {
      // Storage might be full, clear old events
      this.events = this.events.slice(-100);
      try {
        localStorage.setItem(ANALYTICS_KEY, JSON.stringify(this.events));
      } catch {
        // Give up
      }
    }
  }

  setUserId(userId: string | null) {
    this.userId = userId;
  }

  private trackEvent(type: AnalyticsEvent['type'], data: Record<string, unknown>) {
    const event: AnalyticsEvent = {
      type,
      timestamp: Date.now(),
      data: {
        ...data,
        sessionId: this.sessionId,
        userId: this.userId,
      },
    };

    this.events.push(event);
    this.saveEvents();

    // Send to backend if available (batch processing)
    this.sendToBackend(event);
  }

  private async sendToBackend(event: AnalyticsEvent) {
    // In production, you'd batch these and send periodically
    // For now, we'll just log in development
    if (import.meta.env.DEV) {
      console.log('[Analytics]', event);
    }
  }

  private trackSessionStart() {
    this.trackEvent('feature_usage', {
      feature: 'session_start',
      userAgent: navigator.userAgent,
      language: navigator.language,
      screenSize: `${window.screen.width}x${window.screen.height}`,
    });
  }

  trackPageView(path: string) {
    this.trackEvent('pageview', {
      path,
      referrer: document.referrer,
    });
  }

  trackFeatureUsage(feature: string, details?: Record<string, unknown>) {
    this.trackEvent('feature_usage', {
      feature,
      ...details,
    });
  }

  trackPerformance(metric: string, value: number, details?: Record<string, unknown>) {
    this.trackEvent('performance', {
      metric,
      value,
      ...details,
    });
  }

  trackError(error: Error, context?: Record<string, unknown>) {
    this.trackEvent('error', {
      message: error.message,
      stack: error.stack,
      ...context,
    });
  }

  // Get analytics data for dashboard
  getAnalyticsData() {
    const now = Date.now();
    const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1000;

    const recentEvents = this.events.filter((e) => e.timestamp > thirtyDaysAgo);

    // Calculate MAU (Monthly Active Users - unique sessions in last 30 days)
    const uniqueSessions30d = new Set(
      recentEvents.map((e) => e.data.sessionId as string)
    ).size;

    // Daily active users (last 7 days)
    const dailyActiveUsers = this.calculateDailyActiveUsers(recentEvents, 7);

    // Feature adoption
    const featureUsage = this.calculateFeatureUsage(recentEvents);

    // Page views
    const pageViews = this.calculatePageViews(recentEvents);

    // Performance metrics
    const performanceMetrics = this.calculatePerformanceMetrics(recentEvents);

    // Cost predictions
    const costPredictions = this.generateCostPredictions();

    return {
      mau: uniqueSessions30d,
      dailyActiveUsers,
      featureUsage,
      pageViews,
      performanceMetrics,
      costPredictions,
      totalEvents: this.events.length,
    };
  }

  private calculateDailyActiveUsers(events: AnalyticsEvent[], days: number) {
    const dailyUsers: { date: string; users: number }[] = [];
    const now = Date.now();

    for (let i = days - 1; i >= 0; i--) {
      const date = new Date(now - i * 24 * 60 * 60 * 1000);
      const dateStr = date.toISOString().split('T')[0];
      const dayStart = date.setHours(0, 0, 0, 0);
      const dayEnd = dayStart + 24 * 60 * 60 * 1000;

      const dayEvents = events.filter(
        (e) => e.timestamp >= dayStart && e.timestamp < dayEnd
      );
      const uniqueUsers = new Set(dayEvents.map((e) => e.data.sessionId as string)).size;

      dailyUsers.push({ date: dateStr, users: uniqueUsers });
    }

    return dailyUsers;
  }

  private calculateFeatureUsage(events: AnalyticsEvent[]) {
    const featureCounts: Record<string, number> = {};

    events
      .filter((e) => e.type === 'feature_usage')
      .forEach((e) => {
        const feature = e.data.feature as string;
        featureCounts[feature] = (featureCounts[feature] || 0) + 1;
      });

    return Object.entries(featureCounts)
      .map(([feature, count]) => ({ feature, count }))
      .sort((a, b) => b.count - a.count)
      .slice(0, 10);
  }

  private calculatePageViews(events: AnalyticsEvent[]) {
    const pageCounts: Record<string, number> = {};

    events
      .filter((e) => e.type === 'pageview')
      .forEach((e) => {
        const path = e.data.path as string;
        pageCounts[path] = (pageCounts[path] || 0) + 1;
      });

    return Object.entries(pageCounts)
      .map(([path, count]) => ({ path, count }))
      .sort((a, b) => b.count - a.count);
  }

  private calculatePerformanceMetrics(events: AnalyticsEvent[]) {
    const metrics: Record<string, number[]> = {};

    events
      .filter((e) => e.type === 'performance')
      .forEach((e) => {
        const metric = e.data.metric as string;
        const value = e.data.value as number;
        if (!metrics[metric]) {
          metrics[metric] = [];
        }
        metrics[metric].push(value);
      });

    return Object.entries(metrics).map(([metric, values]) => ({
      metric,
      avg: values.reduce((a, b) => a + b, 0) / values.length,
      min: Math.min(...values),
      max: Math.max(...values),
      count: values.length,
    }));
  }

  private generateCostPredictions() {
    // Simple trend analysis for cost predictions
    // In a real app, this would use actual historical cost data
    const currentMonth = 1000;
    const trend = 0.05; // 5% growth

    const predictions = [];
    for (let i = 1; i <= 3; i++) {
      const predicted = currentMonth * Math.pow(1 + trend, i);
      const confidence = Math.max(0.7, 1 - i * 0.1); // Decreasing confidence
      predictions.push({
        month: i,
        predicted,
        confidenceLow: predicted * (1 - (1 - confidence)),
        confidenceHigh: predicted * (1 + (1 - confidence)),
      });
    }

    return predictions;
  }

  // Detect anomalies in cost data
  detectAnomalies(costData: number[]) {
    if (costData.length < 7) return [];

    const avg = costData.reduce((a, b) => a + b, 0) / costData.length;
    const stdDev = Math.sqrt(
      costData.reduce((sq, n) => sq + Math.pow(n - avg, 2), 0) / costData.length
    );

    const threshold = 2; // 2 standard deviations

    return costData
      .map((cost, index) => {
        const zScore = Math.abs((cost - avg) / stdDev);
        if (zScore > threshold) {
          return {
            index,
            cost,
            zScore,
            type: cost > avg ? 'spike' : 'drop',
          };
        }
        return null;
      })
      .filter((a): a is NonNullable<typeof a> => a !== null);
  }
}

// Singleton instance
export const analytics = new AnalyticsService();

// React hook for page view tracking
export function usePageViewTracking() {
  const location = useLocation();

  useEffect(() => {
    analytics.trackPageView(location.pathname);
  }, [location.pathname]);
}

// React hook for feature tracking
export function useFeatureTracking() {
  return useCallback((feature: string, details?: Record<string, unknown>) => {
    analytics.trackFeatureUsage(feature, details);
  }, []);
}

// Performance observer hook
export function usePerformanceTracking() {
  useEffect(() => {
    if ('PerformanceObserver' in window) {
      const observer = new PerformanceObserver((list) => {
        for (const entry of list.getEntries()) {
          if (entry.entryType === 'measure') {
            analytics.trackPerformance(entry.name, entry.duration || 0, {
              entryType: entry.entryType,
            });
          }
        }
      });

      try {
        observer.observe({ entryTypes: ['measure', 'navigation'] });
      } catch {
        // Some entry types may not be supported
      }

      return () => observer.disconnect();
    }
  }, []);
}
