/**
 * Servicio GPS para capturar coordenadas automáticamente
 * Maneja permisos, errores y configuración de precisión
 */

class GPSService {
  constructor() {
    this.watchId = null;
    this.lastKnownPosition = null;
    this.options = {
      enableHighAccuracy: true,
      timeout: 10000,
      maximumAge: 60000 // 1 minuto
    };
  }

  /**
   * Verifica si el navegador soporta geolocalización
   */
  isSupported() {
    return 'geolocation' in navigator;
  }

  /**
   * Solicita permisos de geolocalización
   */
  async requestPermission() {
    if (!this.isSupported()) {
      throw new Error('Geolocalización no soportada en este dispositivo');
    }

    try {
      const permission = await navigator.permissions.query({ name: 'geolocation' });
      return permission.state;
    } catch (error) {
      // Fallback para navegadores que no soportan permissions API
      return 'prompt';
    }
  }

  /**
   * Obtiene la posición actual del dispositivo
   */
  getCurrentPosition() {
    return new Promise((resolve, reject) => {
      if (!this.isSupported()) {
        reject(new Error('Geolocalización no soportada'));
        return;
      }

      navigator.geolocation.getCurrentPosition(
        (position) => {
          const coords = {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            accuracy: position.coords.accuracy,
            timestamp: new Date(position.timestamp)
          };
          
          this.lastKnownPosition = coords;
          resolve(coords);
        },
        (error) => {
          reject(this.handleGeolocationError(error));
        },
        this.options
      );
    });
  }

  /**
   * Inicia el seguimiento continuo de la posición
   */
  startWatching(onPositionUpdate, onError) {
    if (!this.isSupported()) {
      onError(new Error('Geolocalización no soportada'));
      return;
    }

    this.watchId = navigator.geolocation.watchPosition(
      (position) => {
        const coords = {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
          timestamp: new Date(position.timestamp)
        };
        
        this.lastKnownPosition = coords;
        onPositionUpdate(coords);
      },
      (error) => {
        onError(this.handleGeolocationError(error));
      },
      this.options
    );
  }

  /**
   * Detiene el seguimiento de la posición
   */
  stopWatching() {
    if (this.watchId !== null) {
      navigator.geolocation.clearWatch(this.watchId);
      this.watchId = null;
    }
  }

  /**
   * Obtiene la última posición conocida
   */
  getLastKnownPosition() {
    return this.lastKnownPosition;
  }

  /**
   * Maneja errores de geolocalización
   */
  handleGeolocationError(error) {
    switch (error.code) {
      case error.PERMISSION_DENIED:
        return new Error('Permisos de ubicación denegados. Por favor, habilite la ubicación en su dispositivo.');
      case error.POSITION_UNAVAILABLE:
        return new Error('Ubicación no disponible. Verifique que el GPS esté activado.');
      case error.TIMEOUT:
        return new Error('Tiempo de espera agotado. Intente nuevamente.');
      default:
        return new Error('Error desconocido al obtener la ubicación.');
    }
  }

  /**
   * Valida si las coordenadas están dentro de Guatemala
   */
  isValidGuatemalaCoordinates(latitude, longitude) {
    // Límites aproximados de Guatemala
    const guatemalaBounds = {
      north: 17.8193,
      south: 13.7373,
      east: -88.2258,
      west: -92.2714
    };

    return (
      latitude >= guatemalaBounds.south &&
      latitude <= guatemalaBounds.north &&
      longitude >= guatemalaBounds.west &&
      longitude <= guatemalaBounds.east
    );
  }

  /**
   * Formatea coordenadas para mostrar
   */
  formatCoordinates(latitude, longitude) {
    return {
      latitude: parseFloat(latitude.toFixed(8)),
      longitude: parseFloat(longitude.toFixed(8)),
      formatted: `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`
    };
  }
}

export default new GPSService();