// Format Hz to human-readable frequency
export function formatFreq(hz) {
  if (!hz) return '—'
  if (hz >= 1e9) return (hz / 1e9).toFixed(6) + ' GHz'
  if (hz >= 1e6) return (hz / 1e6).toFixed(4) + ' MHz'
  if (hz >= 1e3) return (hz / 1e3).toFixed(2) + ' kHz'
  return hz.toFixed(0) + ' Hz'
}

// Format Doppler shift
export function formatShift(hz) {
  if (hz === null || hz === undefined) return '—'
  const sign = hz >= 0 ? '+' : ''
  if (Math.abs(hz) >= 1000) return `${sign}${(hz / 1000).toFixed(2)} kHz`
  return `${sign}${hz.toFixed(0)} Hz`
}

// Format azimuth with compass direction
export function formatAz(deg) {
  if (deg === null || deg === undefined) return '—'
  const dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
                'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
  const idx = Math.round(deg / 22.5) % 16
  return `${deg.toFixed(1)}° ${dirs[idx]}`
}

// Format elevation
export function formatEl(deg) {
  if (deg === null || deg === undefined) return '—'
  return `${deg.toFixed(1)}°`
}

// Format range in km
export function formatRange(km) {
  if (!km) return '—'
  return `${Math.round(km).toLocaleString('en-US')} km`
}

// Format time to UTC HH:MM:SS
export function formatUTC(date) {
  if (!date) return '—'
  const d = typeof date === 'string' ? new Date(date) : date
  return d.toUTCString().slice(17, 25)
}

// Format duration in seconds to mm:ss or hh:mm:ss
export function formatDuration(secs) {
  if (!secs) return '—'
  const h = Math.floor(secs / 3600)
  const m = Math.floor((secs % 3600) / 60)
  const s = Math.floor(secs % 60)
  if (h > 0) return `${h}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`
  return `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`
}

// Time until a future date
export function timeUntil(date) {
  const d = typeof date === 'string' ? new Date(date) : date
  const diffSecs = Math.floor((d - Date.now()) / 1000)
  if (diffSecs < 0) return 'passed'
  if (diffSecs < 60) return `${diffSecs}s`
  if (diffSecs < 3600) return `${Math.floor(diffSecs/60)}m ${diffSecs%60}s`
  return `${Math.floor(diffSecs/3600)}h ${Math.floor((diffSecs%3600)/60)}m`
}

// Compute Doppler shift for display
export function computeDopplerShift(nominalHz, rangeRateKmS) {
  const c = 299792.458 // km/s
  return nominalHz * (-rangeRateKmS / c)
}

// Elevation class for color coding
export function elClass(el) {
  if (el >= 30) return 'el-high'
  if (el >= 10) return 'el-mid'
  if (el >= 0) return 'el-low'
  return 'el-below'
}

// Signal quality based on max elevation
export function passQuality(maxEl) {
  if (maxEl >= 60) return { label: 'Excellent', cls: 'q-excellent' }
  if (maxEl >= 30) return { label: 'Good', cls: 'q-good' }
  if (maxEl >= 10) return { label: 'Fair', cls: 'q-fair' }
  return { label: 'Poor', cls: 'q-poor' }
}