package app

import (
	"encoding/json"
	"fmt"
	"io"
	"log/slog"
	"net"
	"net/http"
	g "proxy-server/gateway/globals"
	"strings"
)

const base = "https://whois.pconline.com.cn/ipJson.jsp?json=true&ip="

func IpGeo(ip net.IP) (info *IpGeoInfo, err error) {
	defer func() {
		var rs = recover()
		if reErr, ok := rs.(error); ok {
			err = fmt.Errorf("执行归属地查询异常 %w", reErr)
		}
	}()

	// 本地归属地查询
	str, err := g.Geo.SearchByStr(ip.String())
	if err != nil {
		return nil, err
	}
	if str != "" {
		slog.Debug("本地解析归属地结果", "str", str)
		values := strings.Split(str, "|")
		if len(values) != 5 {
			return nil, fmt.Errorf("本地归属地查询解析失败")
		}
		return &IpGeoInfo{
			Prov: values[2],
			City: values[3],
			Isp:  values[4],
		}, nil
	}

	// 归属地查询
	var url = base + ip.String()
	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("查询归属地失败: %w", err)
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("查询归属地失败: %s", resp.Status)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)

	// 返回节点信息
	var bytes []byte
	_, err = io.ReadFull(resp.Body, bytes)
	if err != nil {
		return nil, fmt.Errorf("读取归属地响应失败: %w", err)
	}

	var body = make(map[string]any)
	err = json.Unmarshal(bytes, &body)
	if err != nil {
		return nil, fmt.Errorf("解析归属地响应失败: %w", err)
	}

	return &IpGeoInfo{
		Prov: body["pro"].(string),
		City: body["city"].(string),
		Isp:  strings.Split(body["addr"].(string), " ")[1],
	}, nil
}

type IpGeoInfo struct {
	Prov string
	City string
	Isp  string
}
