package location

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

// StringOrArray ########################### 核心：兼容字符串/数组的自定义类型 ###########################
type StringOrArray string

// UnmarshalJSON 处理字符串/数组两种格式
func (s *StringOrArray) UnmarshalJSON(data []byte) error {
	// 尝试解析为纯字符串
	var str string
	if err := json.Unmarshal(data, &str); err == nil {
		*s = StringOrArray(str)
		return nil
	}

	// 尝试解析为字符串数组
	var strArr []string
	if err := json.Unmarshal(data, &strArr); err != nil {
		return fmt.Errorf("字段解析失败: %v, 原始数据: %s", err, string(data))
	}

	// 数组取第一个元素（高德返回的数组通常仅1个元素）
	if len(strArr) > 0 {
		*s = StringOrArray(strArr[0])
	} else {
		*s = StringOrArray("")
	}
	return nil
}

// String 转为普通字符串，方便使用
func (s StringOrArray) String() string {
	return string(s)
}

// ########################### 严格对齐高德API的结构体 ###########################
// AMapEntity 最终返回的实体（对应Java的AMapEntity）
type AMapEntity struct {
	AddressComponent AddressComponent `json:"addresscomponent"`
	Address          StringOrArray    `json:"formatted_address"` // 改为兼容类型
}

// StreetNumber 门牌号嵌套对象（高德固定返回对象）
type StreetNumber struct {
	Number    StringOrArray `json:"number"`    // 门牌号
	Location  StringOrArray `json:"location"`  // 经纬度
	Direction StringOrArray `json:"direction"` // 方向
	Distance  StringOrArray `json:"distance"`  // 距离
	Street    StringOrArray `json:"street"`    // 所属街道
}

// AddressComponent 地址组件（全量兼容）
type AddressComponent struct {
	Province     StringOrArray `json:"province"`     // 省（字符串/数组）
	City         StringOrArray `json:"city"`         // 市（字符串/数组）
	District     StringOrArray `json:"district"`     // 区（字符串/数组）
	Township     StringOrArray `json:"township"`     // 乡镇（纯字符串）
	Street       StringOrArray `json:"street"`       // 街道（纯字符串）
	StreetNumber StreetNumber  `json:"streetnumber"` // 门牌号（对象）
	Adcode       StringOrArray `json:"adcode"`       // 行政区划编码（纯字符串）
	Country      StringOrArray `json:"country"`      // 国家（纯字符串）
	CountryCode  StringOrArray `json:"countrycode"`  // 国家编码（纯字符串）
}

// AMapResponse 高德API顶层响应
type AMapResponse struct {
	Regeocode Regeocode `json:"regeocode"` // 核心数据
	Status    string    `json:"status"`    // 1=成功，0=失败
	Info      string    `json:"info"`      // 错误信息
	Infocode  string    `json:"infocode"`  // 错误码（精准定位问题）
}

// Regeocode 逆地理编码核心数据
type Regeocode struct {
	FormattedAddress StringOrArray    `json:"formatted_address"` // 改为兼容类型
	AddressComponent AddressComponent `json:"addresscomponent"`  // 地址组件
}

// ########################### 配置常量 ###########################
const (
	appKey     = "1b8dd8848bcc062ff1f2cec6db683673" // 替换为你的有效Key
	amapApiUrl = "https://restapi.amap.com/v3/geocode/regeo"
)

// Point2code 经纬度转地址（完整错误处理+兼容）
func Point2code(longitude, latitude float32) (*AMapEntity, error) {
	// 1. 基础参数校验
	if longitude == 0 || latitude == 0 {
		return nil, errors.New("经纬度不能为0")
	}

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

	// 设置查询参数
	params := url.Values{}
	params.Set("key", appKey)
	params.Set("location", fmt.Sprintf("%f,%f", longitude, latitude))
	baseURL.RawQuery = params.Encode()

	// 3. 全局HTTP客户端（建议单例复用）
	client := &http.Client{Timeout: 10 * time.Second}

	// 4. 发送GET请求
	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() // 强制关闭响应体，避免内存泄漏

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

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

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

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

	// 9. 构造最终返回实体
	result := &AMapEntity{
		AddressComponent: amapResp.Regeocode.AddressComponent,
		Address:          amapResp.Regeocode.FormattedAddress,
	}

	return result, nil
}
