import { computed, onMounted, onUnmounted, ref } from 'vue'

export function formatNetworkRate(bytesPerSecond: number | null, online: boolean) {
  if (!online || bytesPerSecond === null) return 'OFFLINE'
  if (bytesPerSecond >= 1024 * 1024) return `${(bytesPerSecond / (1024 * 1024)).toFixed(2)} MB/s`
  if (bytesPerSecond >= 1024) return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`
  return `${bytesPerSecond.toFixed(0)} B/s`
}

export function useClientTime() {
  const clientTime = ref(new Date())
  const city = ref('Location')
  const weatherSummary = ref('Weather unavailable')
  const weatherCode = ref<number | null>(null)
  let clientTimeTimer: ReturnType<typeof setInterval> | null = null
  const WEATHER_CACHE_KEY = 'jarvis:clientWeather'

  function loadWeatherCache() {
    if (typeof window === 'undefined') return
    try {
      const raw = window.localStorage.getItem(WEATHER_CACHE_KEY)
      if (!raw) return
      const parsed = JSON.parse(raw) as { city?: string; weather_summary?: string; weather_code?: number | null; cached_at?: number }
      if (typeof parsed.city === 'string' && parsed.city.trim()) city.value = parsed.city
      if (typeof parsed.weather_summary === 'string' && parsed.weather_summary.trim()) weatherSummary.value = parsed.weather_summary
      if (typeof parsed.weather_code === 'number') weatherCode.value = parsed.weather_code
    } catch {
      // ignore cache parse errors
    }
  }

  function saveWeatherCache(payload: { city: string; weather_summary: string; weather_code: number | null }) {
    if (typeof window === 'undefined') return
    try {
      window.localStorage.setItem(WEATHER_CACHE_KEY, JSON.stringify({ ...payload, cached_at: Date.now() }))
    } catch {
      // ignore storage errors
    }
  }

  // Read cache synchronously during setup to avoid initial render flicker (icon showing as X/na).
  loadWeatherCache()

  async function loadSystemConfig() {
    try {
      const response = await fetch('/api/system/config')
      if (!response.ok) throw new Error('system config request failed')
      const config = await response.json()
      city.value = typeof config.location === 'string' && config.location.trim() ? config.location : 'Location'
      weatherCode.value = typeof config.weather_code === 'number' ? config.weather_code : null
      weatherSummary.value = typeof config.weather_summary === 'string' && config.weather_summary.trim()
        ? config.weather_summary
        : 'Weather unavailable'
      saveWeatherCache({ city: city.value, weather_summary: weatherSummary.value, weather_code: weatherCode.value })
    } catch {
      // If we already have cached weather on screen, keep it to avoid UI flicker (icon showing as "X"/na).
      const hasExistingWeather = weatherCode.value !== null || (weatherSummary.value && weatherSummary.value !== 'Weather unavailable')
      if (!hasExistingWeather) {
        city.value = 'Location'
        weatherCode.value = null
        weatherSummary.value = 'Weather unavailable'
      }
    }
  }

  function updateClientTime() {
    clientTime.value = new Date()
  }

  function formatClientDate(date: Date) {
    return date.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' })
  }

  function formatClientClock(date: Date) {
    return date.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit', minute: '2-digit', second: '2-digit' })
  }

  function weatherCodeLabel(code: number | null | undefined) {
    // Backend may return wttr.in condition codes (e.g. 113/116/119...), normalize to user-friendly labels.
    if (typeof code === 'number' && code > 99) {
      if (code === 113) return 'Clear'
      if (code === 116) return 'Partly Cloudy'
      if (code === 119 || code === 122) return 'Overcast'
      if (code === 143) return 'Fog'
      if ([200, 386, 389].includes(code)) return 'Thunderstorm'
      if (
        [
          176, 263, 266, 281, 293, 296, 299, 302, 305, 308,
          311, 314, 317, 350, 353, 356, 359, 362,
        ].includes(code)
      ) return 'Rain'
      if (
        [
          179, 182, 185, 227, 230, 323, 326, 329, 332, 335,
          338, 368, 371, 374, 377, 392, 395,
        ].includes(code)
      ) return 'Snow'
      return 'Weather'
    }
    if (code === 0) return 'Clear'
    if (code === 1 || code === 2) return 'Partly Cloudy'
    if (code === 3) return 'Overcast'
    if (code === 45 || code === 48) return 'Fog'
    if ([51, 53, 55, 56, 57].includes(code ?? -1)) return 'Drizzle'
    if ([61, 63, 65, 66, 67, 80, 81, 82].includes(code ?? -1)) return 'Rain'
    if ([71, 73, 75, 77, 85, 86].includes(code ?? -1)) return 'Snow'
    if ([95, 96, 99].includes(code ?? -1)) return 'Thunderstorm'
    return 'Weather unavailable'
  }

  const weatherIcon = computed(() => {
    const code = weatherCode.value
    if (code === null || code === undefined) return ''
    // Support wttr.in weather codes (commonly 113/116/119/122/143/...).
    if (typeof code === 'number' && code > 99) {
      if (code === 113) return 'wi-day-sunny'
      if (code === 116) return 'wi-day-cloudy'
      if (code === 119) return 'wi-cloudy'
      if (code === 122) return 'wi-cloudy'
      if (code === 143) return 'wi-fog'
      if ([200, 386, 389].includes(code)) return 'wi-thunderstorm'
      if (
        [
          176, 263, 266, 281, 293, 296, 299, 302, 305, 308,
          311, 314, 317, 350, 353, 356, 359, 362,
        ].includes(code)
      ) return 'wi-rain'
      if (
        [
          179, 182, 185, 227, 230, 323, 326, 329, 332, 335,
          338, 368, 371, 374, 377, 392, 395,
        ].includes(code)
      ) return 'wi-snow'
      return ''
    }
    if (code === 0) return 'wi-day-sunny'
    if (code === 1) return 'wi-day-cloudy'
    if (code === 2) return 'wi-day-cloudy-gusts'
    if (code === 3) return 'wi-cloudy'
    if (code === 45) return 'wi-day-fog'
    if (code === 48) return 'wi-fog'
    if ([51, 53].includes(code ?? -1)) return 'wi-day-showers'
    if ([55, 56, 57].includes(code ?? -1)) return 'wi-showers'
    if ([61, 63, 65, 80].includes(code ?? -1)) return 'wi-day-rain'
    if ([66, 67, 81, 82].includes(code ?? -1)) return 'wi-rain'
    if ([71, 73, 75, 77, 85, 86].includes(code ?? -1)) return 'wi-snow'
    if ([95, 96, 99].includes(code ?? -1)) return 'wi-thunderstorm'
    return ''
  })

  onMounted(async () => {
    updateClientTime()
    clientTimeTimer = setInterval(updateClientTime, 1000)
    await loadSystemConfig()
  })

  onUnmounted(() => {
    if (clientTimeTimer) clearInterval(clientTimeTimer)
  })

  return {
    clientTime,
    city,
    weatherSummary,
    weatherCode,
    weatherIcon,
    updateClientTime,
    formatClientDate,
    formatClientClock,
    weatherCodeLabel,
    loadSystemConfig,
  }
}
