package api

import (
	"context"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"strconv"
	"strings"
	"time"
)

const (
	api    = "https://api.seniverse.com/v3/weather/now.json?language=zh-Hans&unit=c&location="
	dayApi = "https://api.seniverse.com/v3/weather/daily.json?language=zh-Hans&unit=c&start=-1&days=5&location="
	airApi = "https://api.seniverse.com/v3/air/now.json?language=zh-Hans&scope=city&location="
)

// WeatherResp 天气
type WeatherResp struct {
	Results []struct {
		Location struct {
			Id             string `json:"id"`
			Name           string `json:"name"`
			Country        string `json:"country"`
			Path           string `json:"path"`
			Timezone       string `json:"timezone"`
			TimezoneOffset string `json:"timezone_offset"`
		} `json:"location"`
		Now struct {
			Text                string `json:"text"`
			Code                string `json:"code"`
			Temperature         string `json:"temperature"`
			FeelsLike           string `json:"feels_like"`
			Pressure            string `json:"pressure"`
			Humidity            string `json:"humidity"`
			Visibility          string `json:"visibility"`
			WindDirection       string `json:"wind_direction"`
			WindDirectionDegree string `json:"wind_direction_degree"`
			WindSpeed           string `json:"wind_speed"`
			WindScale           string `json:"wind_scale"`
			Clouds              string `json:"clouds"`
			DewPoint            string `json:"dew_point"`
		} `json:"now"`
		LastUpdate time.Time `json:"last_update"`
	}
}

type XinZhiDayWeatherInfo struct {
	Results []struct {
		Location struct {
			Id             string `json:"id"`
			Name           string `json:"name"`
			Country        string `json:"country"`
			Path           string `json:"path"`
			Timezone       string `json:"timezone"`
			TimezoneOffset string `json:"timezone_offset"`
		} `json:"location"`
		Daily []struct {
			Date                string `json:"date"`
			TextDay             string `json:"text_day"`
			CodeDay             string `json:"code_day"`
			TextNight           string `json:"text_night"`
			CodeNight           string `json:"code_night"`
			High                string `json:"high"`
			Low                 string `json:"low"`
			Rainfall            string `json:"rainfall"`
			Precip              string `json:"precip"`
			WindDirection       string `json:"wind_direction"`
			WindDirectionDegree string `json:"wind_direction_degree"`
			WindSpeed           string `json:"wind_speed"`
			WindScale           string `json:"wind_scale"`
			Humidity            string `json:"humidity"`
		} `json:"daily"`
		LastUpdate time.Time `json:"last_update"`
	} `json:"results"`
}

type AirInfo struct {
	Results []struct {
		Location struct {
			Id             string `json:"id"`
			Name           string `json:"name"`
			Country        string `json:"country"`
			Path           string `json:"path"`
			Timezone       string `json:"timezone"`
			TimezoneOffset string `json:"timezone_offset"`
		} `json:"location"`
		Air struct {
			City struct {
				Aqi              string    `json:"aqi"`               // 空气质量指数(AQI)是描述空气质量状况的定量指数
				Pm25             string    `json:"pm25"`              // PM2.5颗粒物（粒径小于等于2.5μm）1小时平均值。单位：μg/m³
				Pm10             string    `json:"pm10"`              // PM10颗粒物（粒径小于等于10μm）1小时平均值。单位：μg/m³
				So2              string    `json:"so2"`               // 二氧化硫1小时平均值。单位：μg/m³
				No2              string    `json:"no2"`               // 二氧化氮1小时平均值。单位：μg/m³
				Co               string    `json:"co"`                // 一氧化碳1小时平均值。单位：mg/m³
				O3               string    `json:"o3"`                // 臭氧1小时平均值。单位：μg/m³
				PrimaryPollutant string    `json:"primary_pollutant"` // 首要污染物
				Quality          string    `json:"quality"`           // 空气质量类别，有“优、良、轻度污染、中度污染、重度污染、严重污染”6类
				LastUpdate       time.Time `json:"last_update"`       // 数据发布时间
			} `json:"city"`
		} `json:"air"`
		LastUpdate time.Time `json:"last_update"`
	}
}

type WeatherInfoResp struct {
	Location    string    `json:"location"`
	Text        string    `json:"text"`
	Code        string    `json:"code"`
	Temperature int       `json:"temperature"`
	Humidity    int       `json:"humidity"`
	AQI         int       `json:"aqi"`
	PM25        int       `json:"pm25"`
	PM25Text    string    `json:"pm25_text"`
	PM10        int       `json:"pm10"`
	Quality     string    `json:"quality"`
	LastUpdate  time.Time `json:"last_update"`
}

func GetWeatherInfo(location, key string) (*WeatherInfoResp, error) {
	result := new(WeatherInfoResp)
	info, err := GetWeatherInfoByLocation(location, key)
	if err != nil {
		return nil, err
	}
	if len(info.Results) == 0 {
		return nil, errors.New(fmt.Sprintf("天气查询失败:%s", location))
	}
	result.Location = info.Results[0].Location.Name
	result.Text = info.Results[0].Now.Text
	result.Code = info.Results[0].Now.Code
	result.Temperature, _ = strconv.Atoi(info.Results[0].Now.Temperature)
	result.Humidity, _ = strconv.Atoi(info.Results[0].Now.Humidity)
	result.LastUpdate = info.Results[0].LastUpdate
	airInfo, err := GetAirInfoByLocation(location, key)
	if err != nil {
		return nil, err
	}
	result.PM25, _ = strconv.Atoi(airInfo.Results[0].Air.City.Pm25)
	if result.PM25 <= 35 {
		result.PM25Text = "优"
	} else if result.PM25 <= 75 {
		result.PM25Text = "良"
	} else {
		result.PM25Text = "污染"
	}
	result.AQI, _ = strconv.Atoi(airInfo.Results[0].Air.City.Aqi)
	result.PM10, _ = strconv.Atoi(airInfo.Results[0].Air.City.Pm10)
	result.Quality = airInfo.Results[0].Air.City.Quality
	if strings.Contains(airInfo.Results[0].Air.City.Quality, "污染") {
		result.Quality = "污染"
	}
	return result, nil
}

func GetWeatherInfoByLocation(location, key string) (*WeatherResp, error) {
	ctx := context.Background()
	url := fmt.Sprintf("%s%s&key=%s", api, location, key)
	res := g.Client().GetVar(ctx, url)
	var result WeatherResp
	err := res.Scan(&result)
	if err != nil {
		return nil, errors.New("天气查询失败")
	}
	return &result, nil
}

func GetDayWeatherInfoByLocation(location, key string) (*XinZhiDayWeatherInfo, error) {
	ctx := context.Background()
	url := fmt.Sprintf("%s%s&key=%s", dayApi, location, key)
	res := g.Client().GetVar(ctx, url)
	var result XinZhiDayWeatherInfo
	err := res.Scan(&result)
	if err != nil {
		return nil, errors.New("天气查询失败")
	}
	return &result, nil
}

func GetAirInfoByLocation(location, key string) (*AirInfo, error) {
	ctx := context.Background()
	url := fmt.Sprintf("%s%s&key=%s", airApi, location, key)
	res := g.Client().GetVar(ctx, url)
	var result AirInfo
	err := res.Scan(&result)
	if err != nil {
		return nil, errors.New("天气查询失败")
	}
	return &result, nil
}
