"use client";

import { useState, useEffect, useCallback } from "react";

export type GpsStatus = "idle" | "locating" | "success" | "failed" | "denied";

type GpsResult =
  | { ok: true; lat: number; lng: number }
  | { ok: false; reason: "unsupported" | "denied" | "timeout" | "unknown" };

function requestGps(): Promise<GpsResult> {
  return new Promise((resolve) => {
    if (!navigator.geolocation) {
      resolve({ ok: false, reason: "unsupported" });
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (pos) =>
        resolve({ ok: true, lat: pos.coords.latitude, lng: pos.coords.longitude }),
      (err) => {
        const reason =
          err.code === err.PERMISSION_DENIED
            ? "denied"
            : err.code === err.TIMEOUT
              ? "timeout"
              : "unknown";
        resolve({ ok: false, reason });
      },
      { timeout: 8000, enableHighAccuracy: false },
    );
  });
}

async function reverseGeocode(lat: number, lng: number): Promise<string | null> {
  try {
    const res = await fetch(`/api/location/regeo?lat=${lat}&lng=${lng}`);
    const data = await res.json();
    return data.name || data.formatted || null;
  } catch {
    return null;
  }
}

export function useGeolocation() {
  const [status, setStatus] = useState<GpsStatus>("idle");
  const [coords, setCoords] = useState<{ lat: number; lng: number } | null>(null);
  const [locationName, setLocationName] = useState<string | null>(null);

  const locate = useCallback(async () => {
    setStatus("locating");
    const result = await requestGps();
    if (result.ok) {
      setCoords({ lat: result.lat, lng: result.lng });
      setStatus("success");
      const name = await reverseGeocode(result.lat, result.lng);
      if (name) setLocationName(name);
    } else {
      setCoords(null);
      setLocationName(null);
      setStatus(result.reason === "denied" ? "denied" : "failed");
    }
  }, []);

  useEffect(() => {
    locate();
  }, [locate]);

  return { status, coords, locationName, retry: locate };
}
