/**
 * GPS-Tracking-Service.
 *
 * Wenn aktiv: pushed alle paar Sekunden die aktuelle Position als
 * `location_update {lat, lon}` an den RVS-Server, damit Brain-Watcher
 * mit `near()`-Conditions etwas zum Vergleichen haben.
 *
 * Default: AUS. Wird entweder vom User manuell in Settings angeschaltet
 * oder von ARIA via location_tracking-RVS-Message (Brain-Tool
 * `request_location_tracking`).
 *
 * Energie-Schutz: distanceFilter 30m, interval 15s. Echte Fahrt-Updates
 * (Geschwindigkeit) kommen sauber durch, stationaer wird kaum gesendet.
 */

import AsyncStorage from '@react-native-async-storage/async-storage';
import { PermissionsAndroid, Platform, ToastAndroid } from 'react-native';
import Geolocation from '@react-native-community/geolocation';
import rvs from './rvs';

type Listener = (active: boolean) => void;

class GpsTrackingService {
  private watchId: number | null = null;
  private active = false;
  private listeners: Set<Listener> = new Set();
  // Defensive: nicht zu schnell oeffentlich togglen
  private lastChangeAt = 0;

  isActive(): boolean {
    return this.active;
  }

  onChange(cb: Listener): () => void {
    this.listeners.add(cb);
    return () => { this.listeners.delete(cb); };
  }

  private notify() {
    for (const cb of this.listeners) {
      try { cb(this.active); } catch {}
    }
  }

  /** Beim App-Start: gespeicherten Zustand wiederherstellen (Default off). */
  async restoreFromStorage(): Promise<void> {
    try {
      const v = await AsyncStorage.getItem('aria_gps_tracking');
      if (v === 'true') {
        console.log('[gps-track] Restore: war an, starte wieder');
        this.start('Beim Start wiederhergestellt');
      }
    } catch {}
  }

  private async ensurePermission(): Promise<boolean> {
    if (Platform.OS !== 'android') return true;
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
        {
          title: 'GPS-Tracking',
          message: 'ARIA braucht laufende Standort-Updates damit GPS-Watcher (Blitzer-Warner, near()) funktionieren.',
          buttonPositive: 'Erlauben',
          buttonNegative: 'Abbrechen',
        },
      );
      return granted === PermissionsAndroid.RESULTS.GRANTED;
    } catch (e) {
      console.warn('[gps-track] Permission-Fehler:', e);
      return false;
    }
  }

  async start(reason: string = ''): Promise<boolean> {
    if (this.active) return true;
    const ok = await this.ensurePermission();
    if (!ok) {
      ToastAndroid.show('GPS-Tracking: Berechtigung abgelehnt', ToastAndroid.LONG);
      return false;
    }
    try {
      this.watchId = Geolocation.watchPosition(
        (pos) => {
          const lat = pos.coords.latitude;
          const lon = pos.coords.longitude;
          rvs.send('location_update' as any, { lat, lon });
        },
        (err) => {
          console.warn('[gps-track] watchPosition error:', err?.code, err?.message);
        },
        {
          enableHighAccuracy: true,
          distanceFilter: 30,     // erst senden wenn 30m gewandert
          interval: 15000,        // (Android) gewuenschte Frequenz
          fastestInterval: 10000, // (Android) max Frequenz
        } as any,
      );
      this.active = true;
      this.lastChangeAt = Date.now();
      this.notify();
      AsyncStorage.setItem('aria_gps_tracking', 'true').catch(() => {});
      ToastAndroid.show(
        reason ? `GPS-Tracking aktiv (${reason})` : 'GPS-Tracking aktiv',
        ToastAndroid.SHORT,
      );
      console.log('[gps-track] gestartet', reason ? `(${reason})` : '');
      return true;
    } catch (e: any) {
      console.warn('[gps-track] start fehlgeschlagen:', e?.message);
      return false;
    }
  }

  stop(reason: string = ''): void {
    if (!this.active) return;
    if (this.watchId !== null) {
      try { Geolocation.clearWatch(this.watchId); } catch {}
      this.watchId = null;
    }
    this.active = false;
    this.lastChangeAt = Date.now();
    this.notify();
    AsyncStorage.setItem('aria_gps_tracking', 'false').catch(() => {});
    ToastAndroid.show(
      reason ? `GPS-Tracking aus (${reason})` : 'GPS-Tracking aus',
      ToastAndroid.SHORT,
    );
    console.log('[gps-track] gestoppt', reason ? `(${reason})` : '');
  }

  async toggle(reason: string = ''): Promise<void> {
    if (this.active) this.stop(reason);
    else await this.start(reason);
  }
}

export default new GpsTrackingService();
