import { publicApiRequest, protectedApiRequest, API_CONFIG } from '@/config/api';

class AnalyticsService {
  constructor() {
    this.sessionId = null;
    this.cookieConsent = null;
    this.router = null; // Para Next.js router
    this.isRouteChangeListenerActive = false;
    this.currentPath = null;
    this.initializeSession();
  }

  // ============ INTEGRACIÓN CON NEXT.JS ROUTER ============

  // Inicializar escucha de cambios de ruta (NUEVO)
  initializeRouterTracking(router) {
    if (typeof window === 'undefined' || !router) return;
    
    this.router = router;
    
    // Evitar múltiples listeners
    if (this.isRouteChangeListenerActive) {
      this.removeRouterTracking();
    }
    
    // Listener para cambios de ruta exitosos
    const handleRouteChange = (url) => {
      this.handleRouteChange(url);
    };

    // Registrar listeners
    router.events.on('routeChangeComplete', handleRouteChange);
    this.isRouteChangeListenerActive = true;
    this.currentPath = router.asPath;

    // Cleanup function
    this.removeRouterTracking = () => {
      if (router && this.isRouteChangeListenerActive) {
        router.events.off('routeChangeComplete', handleRouteChange);
        this.isRouteChangeListenerActive = false;
      }
    };
  }

  // Manejar cambio de ruta (NUEVO)
  async handleRouteChange(url) {
    if (!this.isAnalyticsEnabled()) return;

    try {
      // Construir URL completa de manera segura
      let fullUrl;
      if (url.startsWith('https://') || url.startsWith('http://')) {
        fullUrl = url;
      } else {
        fullUrl = `${window.location.origin}${url}`;
      }

      const newPath = url.startsWith('/') ? url.split('?')[0].split('#')[0] : `/${url.split('?')[0].split('#')[0]}`;
      
      // Evitar tracking duplicado
      if (newPath === this.currentPath) {
        return;
      }

      const previousPath = this.currentPath;
      this.currentPath = newPath;

      // Determinar referrer interno
      const internalReferrer = previousPath ? 
        `${window.location.origin}${previousPath}` : 
        document.referrer || 'direct';

      // Usar el método original recordVisit
      await this.recordVisit(fullUrl, internalReferrer);

    } catch (error) {
      console.error('Error tracking route change:', error);
    }
  }

  // Limpiar listeners (NUEVO)
  destroy() {
    if (this.removeRouterTracking) {
      this.removeRouterTracking();
    }
  }

  // ============ MÉTODOS ORIGINALES (SIN CAMBIOS) ============

  // Inicializar sesión y verificar consentimiento
  initializeSession() {
    try {
      // Solo ejecutar en el cliente (no en SSR)
      if (typeof window === 'undefined') return;
      
      // Verificar consentimiento de cookies
      const consent = localStorage.getItem('sempreg-cookie-consent');
      if (consent) {
        this.cookieConsent = JSON.parse(consent);
      }

      // Obtener o generar sessionId
      this.sessionId = this.getOrCreateSessionId();
      
      // Establecer ruta actual
      this.currentPath = window.location.pathname;
    } catch (error) {
      console.warn('Error initializing analytics session:', error);
    }
  }

  // Generar ID de sesión único basado en fecha y características del navegador
  generateSessionId() {
    // Solo ejecutar en el cliente
    if (typeof window === 'undefined') return 'server_session';
    
    const date = new Date().toISOString().split('T')[0]; // Solo fecha (YYYY-MM-DD)
    const userAgent = navigator.userAgent;
    const screen = `${window.screen?.width}x${window.screen?.height}`;
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    
    // Crear un hash simple basado en características del navegador y fecha
    const data = `${date}-${userAgent}-${screen}-${timezone}`;
    let hash = 0;
    for (let i = 0; i < data.length; i++) {
      const char = data.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // Convertir a 32-bit integer
    }
    
    return `session_${Math.abs(hash)}_${date}`;
  }

  // Obtener o crear sessionId (basado en fecha)
  getOrCreateSessionId() {
    try {
      // Solo ejecutar en el cliente
      if (typeof window === 'undefined') return 'server_session';
      
      const today = new Date().toISOString().split('T')[0];
      const sessionKey = `analytics_session_id_${today}`;
      
      let sessionId = sessionStorage.getItem(sessionKey);
      if (!sessionId) {
        sessionId = this.generateSessionId();
        sessionStorage.setItem(sessionKey, sessionId);
        
        // Limpiar sessions de días anteriores
        for (let i = 0; i < sessionStorage.length; i++) {
          const key = sessionStorage.key(i);
          if (key && key.startsWith('analytics_session_id_') && key !== sessionKey) {
            sessionStorage.removeItem(key);
          }
        }
      }
      return sessionId;
    } catch (error) {
      // Fallback si sessionStorage no está disponible
      return this.generateSessionId();
    }
  }

  // Verificar si las cookies analíticas están habilitadas
  isAnalyticsEnabled() {
    // Solo ejecutar en el cliente
    if (typeof window === 'undefined') return false;
    
    if (!this.cookieConsent) {
      try {
        const consent = localStorage.getItem('sempreg-cookie-consent');
        if (consent) {
          this.cookieConsent = JSON.parse(consent);
        }
      } catch (error) {
        return false;
      }
    }

    return this.cookieConsent?.accepted && this.cookieConsent?.settings?.analytics !== false;
  }

  // Verificar si ya se registró una visita para esta página hoy
  hasVisitedToday(path) {
    try {
      // Solo ejecutar en el cliente
      if (typeof window === 'undefined') return false;
      
      const sessionId = this.sessionId;
      const today = new Date().toISOString().split('T')[0];
      const visits = JSON.parse(localStorage.getItem('sempreg-visits') || '[]');
      
      // Buscar si ya existe una visita para esta combinación hoy
      return visits.some(visit => {
        const visitDate = new Date(visit.timestamp).toISOString().split('T')[0];
        return visit.sessionId === sessionId && 
               visit.path === path && 
               visitDate === today;
      });
    } catch {
      return false;
    }
  }

  // Registrar visita (público) - Solo una por página por día por usuario
  async recordVisit(url = window.location.href, referrer = document.referrer || 'direct') {
    // Solo ejecutar en el cliente
    if (typeof window === 'undefined') return;
    
    if (!this.isAnalyticsEnabled()) {
      return;
    }

    try {
      // Manejo seguro de URLs
      let path;
      try {
        path = new URL(url).pathname;
      } catch (urlError) {
        // Fallback para URLs relativas
        path = url.startsWith('/') ? url.split('?')[0].split('#')[0] : `/${url.split('?')[0].split('#')[0]}`;
        console.warn('URL parsing fallback used:', path);
      }
      
      // Verificar si ya se registró esta visita hoy
      if (this.hasVisitedToday(path)) {
        return; // No registrar visita duplicada
      }

      const visitData = {
        sessionId: this.sessionId,
        path,
        title: document.title || '',
        timestamp: new Date().toISOString(),
        date: new Date().toISOString().split('T')[0],
        userAgent: navigator.userAgent,
        referrer: referrer === '' ? 'direct' : referrer,
        url,
        ip: "unknown"
      };

      await publicApiRequest(API_CONFIG.ENDPOINTS.VISIT, {
        method: 'POST',
        body: JSON.stringify(visitData)
      });

      // También guardar localmente como backup
      this.saveVisitLocally(visitData);

    } catch (error) {
      
      // Fallback local mejorado
      try {
        let fallbackPath;
        try {
          fallbackPath = new URL(url).pathname;
        } catch {
          fallbackPath = url.startsWith('/') ? url.split('?')[0].split('#')[0] : `/${url.split('?')[0].split('#')[0]}`;
        }
        
        // Verificar duplicados también en el fallback
        if (this.hasVisitedToday(fallbackPath)) {
          return;
        }
        
        // Guardar localmente como fallback
        this.saveVisitLocally({
          sessionId: this.sessionId,
          path: fallbackPath,
          title: document.title || '',
          timestamp: new Date().toISOString(),
          date: new Date().toISOString().split('T')[0],
          url,
          referrer,
          userAgent: navigator.userAgent,
          ip: 'unknown'
        });
        
      } catch (fallbackError) {
        console.error('Error in fallback save:', fallbackError);
      }
    }
  }

  // Guardar visita localmente (fallback) - Usar nueva estructura
  saveVisitLocally(visitData) {
    try {
      // Solo ejecutar en el cliente
      if (typeof window === 'undefined') return;
      
      const visits = JSON.parse(localStorage.getItem('sempreg-visits') || '[]');
      visits.push(visitData);
      
      // Mantener solo las últimas 1000 visitas
      if (visits.length > 1000) {
        visits.shift();
      }
      
      localStorage.setItem('sempreg-visits', JSON.stringify(visits));
      
      // También mantener compatibilidad con el sistema anterior
      const oldVisits = JSON.parse(localStorage.getItem('sempreg-visit-history') || '[]');
      oldVisits.push(visitData);
      if (oldVisits.length > 100) {
        oldVisits.shift();
      }
      localStorage.setItem('sempreg-visit-history', JSON.stringify(oldVisits));
      
      // Incrementar contador total de visitas únicas
      const currentCount = parseInt(localStorage.getItem('sempreg-visit-count') || '0');
      localStorage.setItem('sempreg-visit-count', (currentCount + 1).toString());
      
    } catch (error) {
      console.warn('Error saving visit locally:', error);
    }
  }

  // Registrar evento (público)
  async recordEvent(eventName, eventData = {}) {
    // Solo ejecutar en el cliente
    if (typeof window === 'undefined') return;
    
    if (!this.isAnalyticsEnabled()) return;

    try {
      const event = {
        name: eventName,
        data: eventData,
        timestamp: new Date().toISOString(),
        url: window.location.href,
        userAgent: navigator.userAgent
      };

      await publicApiRequest(API_CONFIG.ENDPOINTS.EVENT, {
        method: 'POST',
        body: JSON.stringify(event)
      });

      // También guardar localmente como backup
      this.saveEventLocally(event);

    } catch (error) {
      console.warn('Error recording event:', error.message);
      // Guardar localmente como fallback
      this.saveEventLocally({
        name: eventName,
        data: eventData,
        timestamp: new Date().toISOString(),
        url: window.location.href
      });
    }
  }

  // Guardar evento localmente (fallback)
  saveEventLocally(event) {
    try {
      // Solo ejecutar en el cliente
      if (typeof window === 'undefined') return;
      
      const events = JSON.parse(localStorage.getItem('sempreg-custom-events') || '[]');
      events.push(event);
      
      // Mantener solo los últimos 100 eventos
      if (events.length > 100) {
        events.shift();
      }
      
      localStorage.setItem('sempreg-custom-events', JSON.stringify(events));
    } catch (error) {
      console.warn('Error saving event locally:', error);
    }
  }

  // Registrar consentimiento de cookies (público)
  async recordCookieConsent(accepted, settings, version = '1.0') {
    try {
      const consentData = {
        accepted,
        timestamp: new Date().toISOString(),
        version,
        settings,
        userAgent: navigator.userAgent
      };

      await publicApiRequest(API_CONFIG.ENDPOINTS.COOKIE_CONSENT, {
        method: 'POST',
        body: JSON.stringify(consentData)
      });

      // Actualizar estado local
      this.cookieConsent = { accepted, settings, timestamp: consentData.timestamp };

    } catch (error) {
      console.warn('Error recording cookie consent:', error.message);
      // Actualizar estado local aunque falle el API
      this.cookieConsent = { accepted, settings, timestamp: new Date().toISOString() };
    }
  }

  // ============ MÉTODOS HELPER (SIN CAMBIOS) ============

  // Métodos helper para eventos comunes
  trackPageView(page = typeof window !== 'undefined' ? window.location.pathname : '/', additionalData = {}) {
    // Solo ejecutar en el cliente
    if (typeof window === 'undefined') return;
    
    // Registrar la visita única (si no se ha visitado hoy)
    this.recordVisit(window.location.href, document.referrer);
    
    // También registrar como evento para tracking adicional
    return this.recordEvent('page_view', { page, ...additionalData });
  }

  trackButtonClick(buttonName, location = '') {
    return this.recordEvent('button_click', { button: buttonName, location });
  }

  trackFormSubmit(formName, success = true) {
    return this.recordEvent('form_submit', { form: formName, success });
  }

  trackDownload(fileName, fileType = '') {
    return this.recordEvent('download', { file: fileName, type: fileType });
  }

  trackExternalLink(url) {
    return this.recordEvent('external_link', { url });
  }

  trackSearch(query, results = 0) {
    return this.recordEvent('search', { query, results });
  }

  trackError(errorMessage, page = typeof window !== 'undefined' ? window.location.pathname : '/') {
    return this.recordEvent('error', { message: errorMessage, page });
  }

  // ============ MÉTODOS PROTEGIDOS (SIN CAMBIOS) ============

  // Obtener métricas generales (protegido - solo admin)
  async getMetrics(accessToken) {
    try {
      const data = await protectedApiRequest(API_CONFIG.ENDPOINTS.METRICS, accessToken);
            return data;
    } catch (error) {
      console.error('Error fetching metrics:', error);
      // Fallback a datos locales
      return this.getLocalMetrics();
    }
  }

  // Obtener métricas detalladas (protegido - solo admin)
  async getDetailedMetrics(accessToken, filters = {}) {
    try {
      const params = new URLSearchParams(filters);
      const endpoint = `${API_CONFIG.ENDPOINTS.DETAILED_METRICS}?${params}`;
      const data = await protectedApiRequest(endpoint, accessToken);
      return data;
    } catch (error) {
      console.error('Error fetching detailed metrics:', error);
      throw error;
    }
  }

  // Obtener eventos (protegido - solo admin)
  async getEvents(accessToken, filters = {}) {
    try {
      const params = new URLSearchParams(filters);
      const endpoint = `${API_CONFIG.ENDPOINTS.EVENTS}?${params}`;
      const data = await protectedApiRequest(endpoint, accessToken);
      return data;
    } catch (error) {
      console.error('Error fetching events:', error);
      throw error;
    }
  }

  // Exportar datos (protegido - solo admin)
  async exportData(accessToken, type = 'visits', format = 'json') {
    try {
      const endpoint = `${API_CONFIG.ENDPOINTS.EXPORT}?type=${type}&format=${format}`;
      
      if (format === 'csv') {
        const response = await fetch(`${API_CONFIG.BASE_URL}${endpoint}`, {
          headers: {
            'Authorization': `Bearer ${accessToken}`
          }
        });
        
        if (!response.ok) {
          throw new Error('Error downloading CSV');
        }
        
        const blob = await response.blob();
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `sempreg-analytics-${type}-${new Date().toISOString().split('T')[0]}.csv`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);
        
        return { success: true, message: 'CSV downloaded successfully' };
      } else {
        const data = await protectedApiRequest(endpoint, accessToken);
        return data;
      }
    } catch (error) {
      console.error('Error exporting data:', error);
      throw error;
    }
  }

  // Obtener métricas desde datos locales (fallback)
  getLocalMetrics() {
    try {
      const visitHistory = JSON.parse(localStorage.getItem('sempreg-visit-history') || '[]');
      const customEvents = JSON.parse(localStorage.getItem('sempreg-custom-events') || '[]');
      const totalVisits = parseInt(localStorage.getItem('sempreg-visit-count') || '0');

      const now = new Date();
      const today = now.toDateString();
      const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
      const monthAgo = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());

      // Calcular métricas básicas
      const todayVisits = visitHistory.filter(v => new Date(v.timestamp).toDateString() === today).length;
      const thisWeekVisits = visitHistory.filter(v => new Date(v.timestamp) >= weekAgo).length;
      const thisMonthVisits = visitHistory.filter(v => new Date(v.timestamp) >= monthAgo).length;
      
      const uniqueSessionIds = new Set(visitHistory.map(v => v.sessionId));
      const uniqueVisitors = uniqueSessionIds.size;

      // Top páginas
      const pageViews = {};
      visitHistory.forEach(visit => {
        try {
          const path = new URL(visit.url).pathname;
          pageViews[path] = (pageViews[path] || 0) + 1;
        } catch (error) {
          pageViews[visit.url] = (pageViews[visit.url] || 0) + 1;
        }
      });
      
      const topPages = Object.entries(pageViews)
        .sort(([,a], [,b]) => b - a)
        .slice(0, 10)
        .map(([page, views]) => ({ page, views }));

      // Top referrers
      const referrers = {};
      visitHistory.forEach(visit => {
        const ref = visit.referrer === 'direct' ? 'Directo' : visit.referrer;
        referrers[ref] = (referrers[ref] || 0) + 1;
      });
      
      const topReferrers = Object.entries(referrers)
        .sort(([,a], [,b]) => b - a)
        .slice(0, 10)
        .map(([referrer, visits]) => ({ referrer, visits }));

      // Estadísticas de navegadores
      const browsers = {};
      visitHistory.forEach(visit => {
        const userAgent = visit.userAgent || '';
        let browser = 'Desconocido';
        
        if (userAgent.includes('Chrome')) browser = 'Chrome';
        else if (userAgent.includes('Firefox')) browser = 'Firefox';
        else if (userAgent.includes('Safari')) browser = 'Safari';
        else if (userAgent.includes('Edge')) browser = 'Edge';
        else if (userAgent.includes('Opera')) browser = 'Opera';
        
        browsers[browser] = (browsers[browser] || 0) + 1;
      });
      
      const browserStats = Object.entries(browsers)
        .sort(([,a], [,b]) => b - a)
        .map(([browser, count]) => ({ browser, count }));

      return {
        totalVisits,
        uniqueVisitors,
        todayVisits,
        thisWeekVisits,
        thisMonthVisits,
        topPages,
        topReferrers,
        browserStats,
        visitHistory: visitHistory.slice(-20) // Últimas 20 visitas
      };
    } catch (error) {
      console.error('Error getting local metrics:', error);
      return {
        totalVisits: 0,
        uniqueVisitors: 0,
        todayVisits: 0,
        thisWeekVisits: 0,
        thisMonthVisits: 0,
        topPages: [],
        topReferrers: [],
        browserStats: [],
        visitHistory: []
      };
    }
  }
}

// Crear instancia única del servicio
const analyticsService = new AnalyticsService();

export default analyticsService;
