import { config } from '@things-factory/env'
import { WeatherService, WeatherData, WeatherAround, Location } from './types.js'

const baseUrl = 'https://api.open-meteo.com/v1/forecast'
const apiKey = config.get('ApiKey')

export async function getWeatherByLocation(location: Location): Promise<WeatherData> {
  const url = `${baseUrl}?apiKey=${apiKey}&latitude=${location.latitude}&longitude=${location.longitude}&current=temperature_2m,windspeed_10m,cloudcover,relative_humidity_2m,shortwave_radiation&timezone=UTC`

  const response = await fetch(url)
  if (!response.ok) throw new Error(`OpenMeteo API request failed: ${response.status}`)

  const data = await response.json()

  return {
    location,
    temperature: { current: data.current.temperature_2m, unit: '°C' },
    wind: { speed: data.current.windspeed_10m, unit: 'm/s', direction: null },
    humidity: data.current.relative_humidity_2m,
    cloudCoverage: data.current.cloudcover,
    solarRadiation: data.current.shortwave_radiation,
    weatherDescription: 'N/A',
    timestamp: new Date().toISOString()
  }
}

export async function getWeatherAroundLocation(location: Location, radius: number): Promise<WeatherAround> {
  // 그리드 크기를 도 단위로 명확히 정의
  const gridSizeDegrees = 0.2 // 약 22km (적도 기준)

  // Open-Meteo API는 grid 파라미터에 도 단위 사용
  const url = `${baseUrl}?latitude=${location.latitude}&longitude=${location.longitude}&grid=${gridSizeDegrees}&hourly=temperature_2m,windspeed_10m,wind_direction_10m,cloudcover,relative_humidity_2m,shortwave_radiation&timezone=UTC`

  const response = await fetch(url)
  if (!response.ok) throw new Error(`OpenMeteo API request failed: ${response.status}`)

  const data = await response.json()
  const weatherPoints = []

  // 2D 격자 구성 (API 응답에서 grid_latitude와 grid_longitude 배열 사용)
  const latitudes = data.grid_latitude || [location.latitude]
  const longitudes = data.grid_longitude || [location.longitude]

  // 2차원 그리드 구성
  for (let latIndex = 0; latIndex < latitudes.length; latIndex++) {
    for (let lonIndex = 0; lonIndex < longitudes.length; lonIndex++) {
      const pointIndex = latIndex * longitudes.length + lonIndex

      // 데이터 포인트가 있는 경우만 추가
      if (data.hourly.temperature_2m[pointIndex] !== undefined) {
        weatherPoints.push({
          location: {
            latitude: latitudes[latIndex],
            longitude: longitudes[lonIndex]
          },
          temperature: {
            current: data.hourly.temperature_2m[pointIndex],
            unit: '°C'
          },
          wind: {
            speed: data.hourly.windspeed_10m[pointIndex],
            unit: 'm/s',
            direction: data.hourly.wind_direction_10m[pointIndex]
          },
          humidity: data.hourly.relative_humidity_2m[pointIndex],
          cloudCoverage: data.hourly.cloudcover[pointIndex],
          solarRadiation: data.hourly.shortwave_radiation[pointIndex],
          weatherDescription: 'N/A',
          timestamp: new Date().toISOString()
        })
      }
    }
  }

  return { center: location, radius, weatherPoints }
}

export async function getGlobalWeatherData(gridResolution: number = 10): Promise<WeatherAround[]> {
  const globalWeatherData: WeatherAround[] = []

  for (let lat = -90; lat <= 90; lat += gridResolution) {
    // 위도에 따라 경도 샘플링 간격 조정
    const lonStep = Math.max(gridResolution * Math.cos((Math.abs(lat) * Math.PI) / 180), gridResolution / 3)

    for (let lon = -180; lon < 180; lon += lonStep) {
      try {
        const regionWeather = await getWeatherAroundLocation({ latitude: lat, longitude: lon }, gridResolution)
        globalWeatherData.push(regionWeather)
      } catch (error) {
        console.error(`Failed to fetch weather for (${lat}, ${lon}):`, error)
      }
    }
  }

  return globalWeatherData
}
