📄 src/lib/gps.svelte.ts
import type { Coords } from "./types";

const CONSENT_KEY = "birdgo-gps-consent";

class GpsService {
  consent = $state<"granted" | "denied" | null>(null);
  position = $state<GeolocationCoordinates | null>(null);

  #watchId: number | null = null;

  constructor() {
    const stored = localStorage.getItem(CONSENT_KEY);
    if (stored === "granted") {
      this.consent = "granted";
      this.#startWatching();
    } else if (stored === "denied") {
      this.consent = "denied";
    }
    // null/missing → first visit, dialog will show
  }

  grant(): void {
    if (!navigator.geolocation) {
      this.deny();
      return;
    }
    navigator.geolocation.getCurrentPosition(
      () => {
        this.consent = "granted";
        localStorage.setItem(CONSENT_KEY, "granted");
        this.#startWatching();
      },
      () => this.deny(),
    );
  }

  deny(): void {
    this.consent = "denied";
    this.#stopWatching();
    localStorage.setItem(CONSENT_KEY, "denied");
  }

  get coords(): Coords | undefined {
    if (!this.position) return undefined;
    return { lat: this.position.latitude, lng: this.position.longitude };
  }

  #startWatching(): void {
    if (!navigator.geolocation || this.#watchId !== null) return;
    this.#watchId = navigator.geolocation.watchPosition(
      (pos) => {
        this.position = pos.coords;
      },
      () => {},
      { enableHighAccuracy: true },
    );
  }

  #stopWatching(): void {
    if (this.#watchId !== null) {
      navigator.geolocation.clearWatch(this.#watchId);
      this.#watchId = null;
    }
    this.position = null;
  }
}

export const gps = new GpsService();