import { describe, expect, it } from "vitest"
import { bearingDegrees, haversineMeters } from "./geo"

describe("haversineMeters", () => {
  it("er 0 for identiske punkt", () => {
    expect(haversineMeters({ lat: 59.9139, lng: 10.7522 }, { lat: 59.9139, lng: 10.7522 })).toBe(0)
  })

  it("matcher en kjent fasit -- Oslo til Bergen, ca. 305 km luftlinje", () => {
    // Oslo sentrum og Bergen sentrum -- ekte koordinater, ekte kjent
    // omtrentlig storsirkel-avstand (ikke kjøreavstand), ikke en oppdiktet
    // verdi. Toleranse ±3 km for koordinat-presisjon.
    const oslo = { lat: 59.9139, lng: 10.7522 }
    const bergen = { lat: 60.3913, lng: 5.3221 }
    const meters = haversineMeters(oslo, bergen)
    expect(meters).toBeGreaterThan(302_000)
    expect(meters).toBeLessThan(308_000)
  })

  it("1 breddegrad ved ekvator er ca. 111.2 km -- kjent geodetisk fasit", () => {
    const meters = haversineMeters({ lat: 0, lng: 0 }, { lat: 1, lng: 0 })
    expect(meters).toBeGreaterThan(110_500)
    expect(meters).toBeLessThan(111_500)
  })

  it("er symmetrisk (a til b == b til a)", () => {
    const a = { lat: 59.91, lng: 10.75 }
    const b = { lat: 59.92, lng: 10.76 }
    expect(haversineMeters(a, b)).toBeCloseTo(haversineMeters(b, a), 6)
  })

  it("golf-relevant kort avstand (typisk slaglengde, ca. 150 m) er presis", () => {
    // 150 m nord for et fast punkt -- ren nord-sør-forskyvning, lett å
    // regne ut fasit for: 150 m / 111 320 m per breddegrad.
    const start = { lat: 59.9, lng: 10.75 }
    const metersNorth = 150
    const end = { lat: 59.9 + metersNorth / 111_320, lng: 10.75 }
    expect(haversineMeters(start, end)).toBeCloseTo(metersNorth, 0)
  })
})

describe("bearingDegrees", () => {
  it("rett nord er 0 grader", () => {
    expect(bearingDegrees({ lat: 59.9, lng: 10.75 }, { lat: 60.0, lng: 10.75 })).toBeCloseTo(0, 1)
  })

  it("rett øst er 90 grader", () => {
    // På ekvator for å unngå meridiankonvergens-forvrengning ved høyere
    // breddegrad -- en ren øst-forskyvning der er den enkleste fasiten.
    expect(bearingDegrees({ lat: 0, lng: 10 }, { lat: 0, lng: 10.1 })).toBeCloseTo(90, 1)
  })

  it("rett sør er 180 grader", () => {
    expect(bearingDegrees({ lat: 59.9, lng: 10.75 }, { lat: 59.8, lng: 10.75 })).toBeCloseTo(180, 1)
  })

  it("rett vest er 270 grader", () => {
    expect(bearingDegrees({ lat: 0, lng: 10 }, { lat: 0, lng: 9.9 })).toBeCloseTo(270, 1)
  })

  it("returnerer alltid en verdi i [0, 360)", () => {
    const a = { lat: 59.91, lng: 10.75 }
    const b = { lat: 59.85, lng: 10.6 }
    const bearing = bearingDegrees(a, b)
    expect(bearing).toBeGreaterThanOrEqual(0)
    expect(bearing).toBeLessThan(360)
  })
})
