"use client"

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

interface LocationData {
  latitude: number
  longitude: number
  accuracy: number
  timestamp: number
}

interface LocationError {
  code: number
  message: string
}

interface LocationSettings {
  enableHighAccuracy: boolean
  timeout: number
  maximumAge: number
}

export function useLocation(
  settings: LocationSettings = {
    enableHighAccuracy: true,
    timeout: 10000,
    maximumAge: 300000, // 5 minutes
  },
) {
  const [location, setLocation] = useState<LocationData | null>(null)
  const [error, setError] = useState<LocationError | null>(null)
  const [loading, setLoading] = useState(false)
  const [watching, setWatching] = useState(false)
  const [watchId, setWatchId] = useState<number | null>(null)

  const requestLocation = useCallback(() => {
    if (!navigator.geolocation) {
      setError({
        code: 0,
        message: "Geolocation is not supported by this browser.",
      })
      return
    }

    setLoading(true)
    setError(null)

    console.log("[v0] Requesting location with settings:", settings)

    navigator.geolocation.getCurrentPosition(
      (position) => {
        const locationData: LocationData = {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
          timestamp: position.timestamp,
        }

        console.log("[v0] Location obtained:", locationData)
        setLocation(locationData)
        setLoading(false)
      },
      (error) => {
        console.error("[v0] Location error:", error)
        setError({
          code: error.code,
          message: getErrorMessage(error.code),
        })
        setLoading(false)
      },
      settings,
    )
  }, [settings])

  const startWatching = useCallback(() => {
    if (!navigator.geolocation || watching) return

    console.log("[v0] Starting location watching")
    setWatching(true)
    setError(null)

    const id = navigator.geolocation.watchPosition(
      (position) => {
        const locationData: LocationData = {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
          timestamp: position.timestamp,
        }

        console.log("[v0] Location updated:", locationData)
        setLocation(locationData)
      },
      (error) => {
        console.error("[v0] Location watch error:", error)
        setError({
          code: error.code,
          message: getErrorMessage(error.code),
        })
      },
      settings,
    )

    setWatchId(id)
  }, [settings, watching])

  const stopWatching = useCallback(() => {
    if (watchId !== null) {
      console.log("[v0] Stopping location watching")
      navigator.geolocation.clearWatch(watchId)
      setWatchId(null)
      setWatching(false)
    }
  }, [watchId])

  const calculateDistance = useCallback((lat1: number, lon1: number, lat2: number, lon2: number) => {
    const R = 6371 // Radius of the Earth in kilometers
    const dLat = (lat2 - lat1) * (Math.PI / 180)
    const dLon = (lon2 - lon1) * (Math.PI / 180)
    const a =
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) * Math.sin(dLon / 2) * Math.sin(dLon / 2)
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
    const distance = R * c
    return Math.round(distance * 10) / 10 // Round to 1 decimal place
  }, [])

  const getLocationAccuracy = useCallback((accuracy: number) => {
    if (accuracy <= 10) return "high"
    if (accuracy <= 100) return "medium"
    return "low"
  }, [])

  const isLocationStale = useCallback((timestamp: number, maxAge = 300000) => {
    return Date.now() - timestamp > maxAge
  }, [])

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (watchId !== null) {
        navigator.geolocation.clearWatch(watchId)
      }
    }
  }, [watchId])

  return {
    location,
    error,
    loading,
    watching,
    requestLocation,
    startWatching,
    stopWatching,
    calculateDistance,
    getLocationAccuracy: location ? getLocationAccuracy(location.accuracy) : null,
    isLocationStale: location ? isLocationStale(location.timestamp) : false,
  }
}

function getErrorMessage(code: number): string {
  switch (code) {
    case 1:
      return "Location access denied by user."
    case 2:
      return "Location information is unavailable."
    case 3:
      return "Location request timed out."
    default:
      return "An unknown error occurred while retrieving location."
  }
}
