import axios from 'axios'
import localforage from 'localforage'
import { AirQuality, AqiData, StorageData } from '../types'
import { API_RESPONSE_STATUS } from '../utils'

if (!process.env.AQI_TOKEN) console.warn('Env variable not found. Skipping API call.')
const TOKEN = process.env.AQI_TOKEN

const refetchData = (referenceDate: Date, updateTime: number): boolean => {
  const now = new Date()

  const sameYear = referenceDate.getFullYear() === now.getFullYear()
  const sameMonth = referenceDate.getMonth() === now.getMonth()
  const sameDay = referenceDate.getDate() === now.getDate()

  if (sameYear && sameMonth && sameDay) {
    const differenceMilliseconds = Math.abs(now.getTime() - referenceDate.getTime())
    return differenceMilliseconds >= updateTime
  }
  return true
}

const requestData = async (cityInput: string): Promise<AirQuality | null> => {
  const URL = `https://api.waqi.info/feed/${cityInput}/?token=${TOKEN}`
  try {
    const response = await axios.get<AirQuality>(URL)
    if (response?.status === 200) {
      return response.data
    }
    return null
  } catch (error) {
    console.error('Error fetching AQI data:', error)
    return null
  }
}

const processData = (response: AirQuality | null, cityInput: string, defaultMsg: string): AqiData => {
  let data: AqiData = { city: cityInput, station: defaultMsg }
  if (response?.status === API_RESPONSE_STATUS.OK) {
    data = {
      aqi: response.data.aqi,
      city: cityInput,
      station: response.data.city.name
    }
  }
  return data
}

export const getData = async (cityInput: string, updateTime: number, defaultMsg: string): Promise<AqiData> => {
  const storageData: StorageData | null = await localforage.getItem('aqi')
  let data
  if (!storageData?.item || storageData?.item.city !== cityInput || !storageData?.date || refetchData(new Date(storageData.date), updateTime)) {
    data = await requestData(cityInput)
    const processedData = processData(data, cityInput, defaultMsg)
    await localforage.setItem('aqi', { item: processedData, date: new Date() })
    return processedData
  } else {
    data = storageData.item
    return data
  }
}
