"use client"

import { useEffect, useRef, useState } from "react"
import { TargetDistance } from "@/components/target-distance"
import { haversineMeters, type LatLng } from "@/lib/geo"

// Rangefinder-datalag (ADR-064) -- henter rundens rå banepunkter (grønn
// front/midt/bak, hindringer) og kombinerer dem klient-side med spillerens
// LIVE GPS-posisjon via samme watchPosition-mønster som map-point-picker.tsx
// allerede bruker for slagmåling (ADR-048 tillegg 2026-08-08 del 2) --
// `enableHighAccuracy`, grasiøs degradering ved avslått tillatelse,
// `clearWatch` ved avmontering. `TargetDistance` selv forblir "dum"
// (V0-eksportert, ren visning) -- all logikk bor her. Ingen egen
// rad-wrapper (border/padding) her -- kalleren styrer plassering/bredde.
// Montert i PlayerHoleCards sin hull-navigator (round-detail.tsx),
// size="full" -- IKKE i ScoringWizard-headeren (der den satt først,
// 2026-08-12): brukeren pekte ut hovedvisningen som riktig sted og ba
// om mer bredde enn den opprinnelige kompaktvarianten, 2026-08-13.
//
// Strømsparing (2026-08-13, brukerrapport om høyt batteriforbruk):
// (1) `maximumAge` satt til 4000ms (var 1000ms) -- en golfer beveger seg
// ~1,5 m/s, oppdatering hvert 4. sekund er umerkelig i praksis men ber
// GPS-brikken om et ferskt fix mye sjeldnere. (2) `watchPosition` pauses
// helt når fanen/appen ikke er synlig (`document.visibilitychange`) --
// ingen vits å holde GPS-en aktiv for en skjerm ingen ser på (skjerm låst,
// annen app i forgrunnen), og gjenopptas automatisk når brukeren kommer
// tilbake. `enableHighAccuracy` beholdt UENDRET -- lav nøyaktighet ville
// gitt titalls meters feilmargin, for upresist til at front/midt/bak-
// tallene gir mening.

type ApiTargetPoint = {
  poi_type: string
  location: "front" | "middle" | "back" | null
  side_fairway: "left" | "center" | "right" | null
  latitude: number
  longitude: number
}

const _HAZARD_LABELS: Record<string, string> = {
  green_bunker: "Bunker (green)",
  fairway_bunker: "Bunker (fairway)",
  water: "Vannhinder",
  rock: "Fjellknaus",
}

export function HoleTargetDistance({
  roundId,
  holeNumber,
  size = "compact",
  className,
}: {
  roundId: string
  holeNumber: number
  size?: "compact" | "full"
  className?: string
}) {
  const [points, setPoints] = useState<ApiTargetPoint[] | null>(null)
  const [livePosition, setLivePosition] = useState<LatLng | null>(null)
  const [isLive, setIsLive] = useState(false)
  const watchIdRef = useRef<number | null>(null)

  useEffect(() => {
    let cancelled = false
    setPoints(null)
    fetch(`/rounds/${roundId}/holes/${holeNumber}/target-points`, { credentials: "include" })
      .then((res) => (res.ok ? res.json() : []))
      .then((data: ApiTargetPoint[]) => {
        if (!cancelled) setPoints(data)
      })
      .catch(() => {
        if (!cancelled) setPoints([])
      })
    return () => {
      cancelled = true
    }
  }, [roundId, holeNumber])

  useEffect(() => {
    // Ingen vits å spore GPS når banen uansett ikke har koordinatdata for
    // dette hullet -- unngår unødvendig batteribruk/tillatelses-prompt.
    if (!points || points.length === 0) return
    if (typeof navigator === "undefined" || !navigator.geolocation) return
    if (typeof document === "undefined") return

    function startWatch() {
      watchIdRef.current = navigator.geolocation.watchPosition(
        (pos) => {
          setLivePosition({ lat: pos.coords.latitude, lng: pos.coords.longitude })
          setIsLive(true)
        },
        () => {
          // Avslått/feilet -- degraderer grasiøst, komponenten viser bare "ingen data".
          setIsLive(false)
        },
        { enableHighAccuracy: true, maximumAge: 4000 },
      )
    }

    function stopWatch() {
      if (watchIdRef.current !== null && typeof navigator !== "undefined" && navigator.geolocation) {
        navigator.geolocation.clearWatch(watchIdRef.current)
      }
      watchIdRef.current = null
    }

    // Pauser GPS-sporingen helt når fanen/appen ikke er synlig (skjerm
    // låst, annen app i forgrunnen) -- gjenopptas automatisk når brukeren
    // kommer tilbake. `isLive` settes til false mens pauset, så visningen
    // tydelig viser "ikke live" fremfor å late som tallet fortsatt oppdateres.
    function handleVisibilityChange() {
      if (document.hidden) {
        stopWatch()
        setIsLive(false)
      } else {
        startWatch()
      }
    }

    if (!document.hidden) startWatch()
    document.addEventListener("visibilitychange", handleVisibilityChange)

    return () => {
      document.removeEventListener("visibilitychange", handleVisibilityChange)
      stopWatch()
    }
  }, [points])

  // Fortsatt laster, ELLER banen har rett og slett ingen koordinatdata
  // (det store flertallet av runder, TeeOff-baner har ingen GolfAPI-kobling)
  // -- ingen synlig rad i det hele tatt, ikke en "ingen data"-lapp på HVER
  // eneste runde. Lappen (TargetDistance sin egen null-tilstand) er forbeholdt
  // "banen HAR data, men venter på GPS-posisjon ennå" -- da vet vi det er
  // verdt å vise noe.
  if (points === null || points.length === 0) return null
  if (!livePosition) {
    return <TargetDistance size={size} distances={null} isLive={false} className={className} />
  }

  const greenPoints = points.filter((p) => p.poi_type === "green" && p.location)
  const front = greenPoints.find((p) => p.location === "front")
  const middle = greenPoints.find((p) => p.location === "middle")
  const back = greenPoints.find((p) => p.location === "back")
  if (!front || !middle || !back) {
    return <TargetDistance size={size} distances={null} isLive={false} className={className} />
  }

  const distances = {
    front: Math.round(haversineMeters(livePosition, { lat: front.latitude, lng: front.longitude })),
    middle: Math.round(haversineMeters(livePosition, { lat: middle.latitude, lng: middle.longitude })),
    back: Math.round(haversineMeters(livePosition, { lat: back.latitude, lng: back.longitude })),
  }

  const hazards = points.filter((p) => p.poi_type in _HAZARD_LABELS)
  let nearestHazard: { label: string; distanceMeters: number } | null = null
  for (const h of hazards) {
    const d = haversineMeters(livePosition, { lat: h.latitude, lng: h.longitude })
    if (nearestHazard === null || d < nearestHazard.distanceMeters) {
      const base = _HAZARD_LABELS[h.poi_type]
      const label = h.location === "front" || h.location === "back" ? `${base} (${h.location === "front" ? "front" : "bak"})` : base
      nearestHazard = { label, distanceMeters: Math.round(d) }
    }
  }

  return (
    <TargetDistance size={size} distances={distances} nearestHazard={nearestHazard} isLive={isLive} className={className} />
  )
}
