package location

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"time"
)

// ########################### 1. 结构体定义（对齐高德天气API返回格式） ###########################
// WeatherResponse 高德天气API顶层响应结构体
type WeatherResponse struct {
	Status    string        `json:"status"`    // 1=成功，0=失败
	Info      string        `json:"info"`      // 错误信息
	Infocode  string        `json:"infocode"`  // 错误码
	Lives     []LiveWeather `json:"lives"`     // 实时天气（数组，仅1条数据）
	Forecasts []Forecast    `json:"forecasts"` // 天气预报（数组，仅1条数据）
}

// LiveWeather 实时天气结构体
type LiveWeather struct {
	Province      string `json:"province"`      // 省份
	City          string `json:"city"`          // 城市
	Adcode        string `json:"adcode"`        // 行政区划编码
	Weather       string `json:"weather"`       // 天气现象（如晴、阴）
	Temperature   string `json:"temperature"`   // 实时气温（℃）
	WindDirection string `json:"winddirection"` // 风向（如东、西南）
	WindPower     string `json:"windpower"`     // 风力（如3级）
	Humidity      string `json:"humidity"`      // 湿度（%）
	ReportTime    string `json:"reporttime"`    // 数据更新时间
}

// Forecast 天气预报顶层结构体（包含多日预报）
type Forecast struct {
	Province   string        `json:"province"`   // 省份
	City       string        `json:"city"`       // 城市
	Adcode     string        `json:"adcode"`     // 行政区划编码
	ReportTime string        `json:"reporttime"` // 预报发布时间
	Casts      []ForecastDay `json:"casts"`      // 每日预报（未来3天）
}

// ForecastDay 单日天气预报
type ForecastDay struct {
	Date           string `json:"date"`           // 日期（yyyy-MM-dd）
	Week           string `json:"week"`           // 星期（1=周一，7=周日）
	DayWeather     string `json:"dayweather"`     // 白天天气
	NightWeather   string `json:"nightweather"`   // 夜间天气
	DayTemp        string `json:"daytemp"`        // 白天温度
	NightTemp      string `json:"nighttemp"`      // 夜间温度
	DayWindDir     string `json:"daywinddir"`     // 白天风向
	NightWindDir   string `json:"nightwinddir"`   // 夜间风向
	DayWindPower   string `json:"daywindpower"`   // 白天风力
	NightWindPower string `json:"nightwindpower"` // 夜间风力
}

// ########################### 2. 配置常量 ###########################
const (
	amapWeatherApi = "https://restapi.amap.com/v3/weather/weatherInfo"
)

// GetWeather 根据行政区划编码查询天气
// adcode: 行政区划编码（如110101=北京市东城区）
// extensions: 查询类型（base=实时，all=实时+预报）
func GetWeather(adcode string, extensions string) (*WeatherResponse, error) {
	// 1. 参数校验
	if adcode == "" {
		return nil, errors.New("行政区划编码adcode不能为空")
	}
	if extensions == "" {
		extensions = "base" // 默认查实时天气
	}
	if extensions != "base" && extensions != "all" {
		return nil, errors.New("extensions仅支持base（实时）或all（实时+预报）")
	}

	// 2. 构建请求URL和参数
	baseURL, err := url.Parse(amapWeatherApi)
	if err != nil {
		log.Printf("解析基础URL失败: %v", err)
		return nil, err
	}

	// 设置查询参数
	params := url.Values{}
	params.Set("key", appKey)
	params.Set("city", adcode) // 核心参数：行政区划编码
	params.Set("extensions", extensions)
	params.Set("output", "json") // 固定返回JSON格式
	baseURL.RawQuery = params.Encode()

	// 3. 发送HTTP请求（全局客户端，复用连接）
	client := &http.Client{
		Timeout: 10 * time.Second, // 10秒超时
	}
	req, err := http.NewRequest(http.MethodGet, baseURL.String(), nil)
	if err != nil {
		log.Printf("构建请求失败: %v", err)
		return nil, err
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Printf("发送请求失败: %v", err)
		return nil, err
	}
	defer resp.Body.Close() // 强制关闭响应体

	// 4. 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		errMsg := fmt.Sprintf("请求失败，状态码: %d", resp.StatusCode)
		log.Println(errMsg)
		return nil, errors.New(errMsg)
	}

	// 5. 读取响应体
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("读取响应体失败: %v", err)
		return nil, err
	}

	// 6. 解析JSON响应
	var weatherResp WeatherResponse
	if err := json.Unmarshal(bodyBytes, &weatherResp); err != nil {
		log.Printf("解析JSON失败: %v, 响应内容: %s", err, string(bodyBytes))
		return nil, err
	}

	// 7. 检查API业务状态
	if weatherResp.Status != "1" {
		errMsg := fmt.Sprintf("高德天气API返回失败: status=%s, info=%s, infocode=%s",
			weatherResp.Status, weatherResp.Info, weatherResp.Infocode)
		log.Println(errMsg)
		return nil, errors.New(errMsg)
	}

	// 8. 校验返回数据非空
	if extensions == "base" && len(weatherResp.Lives) == 0 {
		return nil, errors.New("未查询到实时天气数据")
	}
	if extensions == "all" && (len(weatherResp.Lives) == 0 || len(weatherResp.Forecasts) == 0) {
		return nil, errors.New("未查询到天气数据（实时/预报）")
	}

	return &weatherResp, nil
}

// ########################### 4. 测试示例 ###########################
func main() {
	// 示例1：查询北京市东城区（adcode=110101）实时天气
	adcode := "110101"
	// 可选：extensions="all" 查询实时+未来3天预报
	weatherResp, err := GetWeather(adcode, "base")
	if err != nil {
		log.Fatalf("查询天气失败: %v", err)
	}

	// 打印实时天气
	fmt.Println("=== 实时天气 ===")
	live := weatherResp.Lives[0] // 实时天气数组仅1条数据
	fmt.Printf("省份：%s\n", live.Province)
	fmt.Printf("城市：%s\n", live.City)
	fmt.Printf("行政区划编码：%s\n", live.Adcode)
	fmt.Printf("天气：%s\n", live.Weather)
	fmt.Printf("实时气温：%s℃\n", live.Temperature)
	fmt.Printf("风向：%s\n", live.WindDirection)
	fmt.Printf("风力：%s级\n", live.WindPower)
	fmt.Printf("湿度：%s%%\n", live.Humidity)
	fmt.Printf("数据更新时间：%s\n", live.ReportTime)

	// 若查询的是all（实时+预报），打印预报数据
	// if len(weatherResp.Forecasts) > 0 {
	// 	fmt.Println("\n=== 未来3天预报 ===")
	// 	forecast := weatherResp.Forecasts[0]
	// 	for _, day := range forecast.Casts {
	// 		fmt.Printf("\n日期：%s（星期%s）\n", day.Date, day.Week)
	// 		fmt.Printf("白天天气：%s，温度：%s℃\n", day.DayWeather, day.DayTemp)
	// 		fmt.Printf("夜间天气：%s，温度：%s℃\n", day.NightWeather, day.NightTemp)
	// 		fmt.Printf("白天风向/风力：%s/%s级\n", day.DayWindDir, day.DayWindPower)
	// 	}
	// }
}
