// Service Worker Registration and Update Management for SIF-GT PWA

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
  window.location.hostname === '[::1]' ||
  window.location.hostname.match(
    /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
  )
);

// Configuration for service worker registration
const SW_CONFIG = {
  swUrl: `${process.env.PUBLIC_URL}/sw.js`,
  scope: '/',
  updateCheckInterval: 60000, // Check for updates every minute
  maxRetries: 3
};

let registration = null;
let updateAvailable = false;
let retryCount = 0;

// Register service worker
export function register(config = {}) {
  if ('serviceWorker' in navigator) {
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      return;
    }

    window.addEventListener('load', () => {
      registerSW(config);
    });
  }
}

// Register the service worker
async function registerSW(config) {
  try {
    registration = await navigator.serviceWorker.register(SW_CONFIG.swUrl, {
      scope: SW_CONFIG.scope
    });

    console.log('Service Worker registered successfully:', registration);

    // Set up event listeners
    setupServiceWorkerListeners(registration, config);

    // Check for updates periodically
    setInterval(() => {
      checkForUpdates();
    }, SW_CONFIG.updateCheckInterval);

    // Initial update check
    setTimeout(() => checkForUpdates(), 1000);

  } catch (error) {
    console.error('Service Worker registration failed:', error);
    
    if (retryCount < SW_CONFIG.maxRetries) {
      retryCount++;
      console.log(`Retrying service worker registration (${retryCount}/${SW_CONFIG.maxRetries})`);
      setTimeout(() => registerSW(config), 5000);
    }
  }
}

// Set up service worker event listeners
function setupServiceWorkerListeners(registration, config) {
  // Listen for service worker updates
  registration.addEventListener('updatefound', () => {
    const installingWorker = registration.installing;
    
    if (installingWorker) {
      installingWorker.addEventListener('statechange', () => {
        if (installingWorker.state === 'installed') {
          if (navigator.serviceWorker.controller) {
            // New content is available
            updateAvailable = true;
            console.log('New content is available; please refresh.');
            
            if (config.onUpdate) {
              config.onUpdate(registration);
            }
            
            showUpdateNotification();
          } else {
            // Content is cached for offline use
            console.log('Content is cached for offline use.');
            
            if (config.onSuccess) {
              config.onSuccess(registration);
            }
          }
        }
      });
    }
  });

  // Listen for messages from service worker
  navigator.serviceWorker.addEventListener('message', handleServiceWorkerMessage);

  // Listen for controller change (new service worker activated)
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    console.log('Service Worker controller changed');
    
    if (updateAvailable) {
      // Reload the page to get the new content
      window.location.reload();
    }
  });
}

// Handle messages from service worker
function handleServiceWorkerMessage(event) {
  const { data } = event;
  
  console.log('Received message from Service Worker:', data);
  
  switch (data.type) {
    case 'SW_UPDATE_AVAILABLE':
      updateAvailable = true;
      showUpdateNotification();
      break;
      
    case 'SW_ACTIVATED':
      console.log('Service Worker activated:', data.message);
      break;
      
    case 'FIELD_DATA_SYNC_COMPLETE':
      showSyncCompletionMessage(data);
      break;
      
    case 'FIELD_DATA_SYNC_ERROR':
      showSyncErrorMessage(data);
      break;
      
    case 'SYNC_ATTEMPT':
      console.log('Sync attempt:', data.message);
      break;
      
    default:
      console.log('Unknown message type:', data.type);
  }
}

// Show update notification to user
function showUpdateNotification() {
  // Create a custom notification element
  const notification = document.createElement('div');
  notification.id = 'sw-update-notification';
  notification.style.cssText = `
    position: fixed;
    top: 20px;
    right: 20px;
    background: #2196F3;
    color: white;
    padding: 16px 20px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    z-index: 10000;
    max-width: 300px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 1.4;
  `;
  
  notification.innerHTML = `
    <div style="margin-bottom: 12px;">
      <strong>Nueva versión disponible</strong>
    </div>
    <div style="margin-bottom: 12px;">
      Hay una nueva versión de la aplicación disponible.
    </div>
    <div style="display: flex; gap: 8px;">
      <button id="sw-update-btn" style="
        background: white;
        color: #2196F3;
        border: none;
        padding: 6px 12px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 12px;
        font-weight: 500;
      ">Actualizar</button>
      <button id="sw-dismiss-btn" style="
        background: transparent;
        color: white;
        border: 1px solid white;
        padding: 6px 12px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 12px;
      ">Después</button>
    </div>
  `;
  
  // Remove existing notification if present
  const existing = document.getElementById('sw-update-notification');
  if (existing) {
    existing.remove();
  }
  
  document.body.appendChild(notification);
  
  // Add event listeners
  document.getElementById('sw-update-btn').addEventListener('click', () => {
    applyUpdate();
    notification.remove();
  });
  
  document.getElementById('sw-dismiss-btn').addEventListener('click', () => {
    notification.remove();
  });
  
  // Auto-dismiss after 10 seconds
  setTimeout(() => {
    if (document.getElementById('sw-update-notification')) {
      notification.remove();
    }
  }, 10000);
}

// Show sync completion message
function showSyncCompletionMessage(data) {
  let message = `Sincronización completada: ${data.synced} registros sincronizados`;
  
  if (data.failed > 0) {
    message += `, ${data.failed} fallidos`;
  }
  
  showToast(message, 'success');
}

// Show sync error message
function showSyncErrorMessage(data) {
  showToast(`Error de sincronización: ${data.error}`, 'error');
}

// Show toast notification
function showToast(message, type = 'info') {
  const toast = document.createElement('div');
  toast.style.cssText = `
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    background: ${type === 'error' ? '#f44336' : type === 'success' ? '#4caf50' : '#2196F3'};
    color: white;
    padding: 12px 20px;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
    z-index: 10000;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    max-width: 400px;
    text-align: center;
  `;
  
  toast.textContent = message;
  document.body.appendChild(toast);
  
  // Auto-remove after 5 seconds
  setTimeout(() => {
    if (toast.parentNode) {
      toast.remove();
    }
  }, 5000);
}

// Apply service worker update
export function applyUpdate() {
  if (registration && registration.waiting) {
    // Tell the waiting service worker to skip waiting
    registration.waiting.postMessage({ type: 'SKIP_WAITING' });
  }
}

// Check for service worker updates
export function checkForUpdates() {
  if (registration) {
    registration.update().catch(error => {
      console.log('Update check failed:', error);
    });
  }
}

// Get service worker version
export async function getServiceWorkerVersion() {
  return new Promise((resolve) => {
    if (navigator.serviceWorker.controller) {
      const messageChannel = new MessageChannel();
      
      messageChannel.port1.onmessage = (event) => {
        resolve(event.data.version || 'unknown');
      };
      
      navigator.serviceWorker.controller.postMessage(
        { type: 'GET_VERSION' },
        [messageChannel.port2]
      );
    } else {
      resolve('not-registered');
    }
  });
}

// Clear all service worker caches
export async function clearServiceWorkerCaches() {
  return new Promise((resolve, reject) => {
    if (navigator.serviceWorker.controller) {
      const messageChannel = new MessageChannel();
      
      messageChannel.port1.onmessage = (event) => {
        if (event.data.success) {
          resolve();
        } else {
          reject(new Error(event.data.error));
        }
      };
      
      navigator.serviceWorker.controller.postMessage(
        { type: 'CLEAR_CACHE' },
        [messageChannel.port2]
      );
    } else {
      reject(new Error('Service Worker not available'));
    }
  });
}

// Force background sync
export function forceBackgroundSync() {
  if (navigator.serviceWorker.controller) {
    navigator.serviceWorker.controller.postMessage({
      type: 'FORCE_SYNC'
    });
  }
}

// Unregister service worker
export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready
      .then(registration => {
        registration.unregister();
      })
      .catch(error => {
        console.error(error.message);
      });
  }
}

// Check if app is running in standalone mode (installed as PWA)
export function isStandalone() {
  return window.matchMedia('(display-mode: standalone)').matches ||
         (window.navigator && window.navigator.standalone === true);
}

// Check if service worker is supported
export function isServiceWorkerSupported() {
  return 'serviceWorker' in navigator;
}

// Check if background sync is supported
export function isBackgroundSyncSupported() {
  return 'serviceWorker' in navigator && 'sync' in window.ServiceWorkerRegistration.prototype;
}

// Check if push notifications are supported
export function isPushNotificationSupported() {
  return 'serviceWorker' in navigator && 'PushManager' in window;
}

// Get service worker registration
export function getRegistration() {
  return registration;
}

// Export default configuration
export default {
  register,
  unregister,
  applyUpdate,
  checkForUpdates,
  getServiceWorkerVersion,
  clearServiceWorkerCaches,
  forceBackgroundSync,
  isStandalone,
  isServiceWorkerSupported,
  isBackgroundSyncSupported,
  isPushNotificationSupported,
  getRegistration
};