package cache

import (
	"ehttp/http"
	"epur-pay/pkg/logger"
	"epur-pay/pkg/redis"
	"errors"
	"fmt"
	"github.com/oschwald/geoip2-golang"
	"net"
	"reflect"
	"runtime"
)

const IpStoreKey = "ipAA"

func NewIpLocation() {
	go func() {
		if err := LoadIpStore(); err != nil && err.Error() == "加载IP库失败,未找到IP库" {
			_ = GetIpStore(Global.Caches.Config.Get("IpStoreRemoteAddr"))
		}
	}()
}

func LoadIpStore() (err error) {

	conn := redis.RPool.Get()

	defer func() {
		if err1 := conn.Close(); err1 != nil {
			logger.ErrorLogger.Infoln(err1.Error())
			err = err1
		}
	}()

	var reply interface{}

	if reply, err = conn.Do("GET", IpStoreKey); err != nil {
		logger.AccessLogger.Errorln("加载IP库失败:", err.Error())
		return
	} else if reply != nil {
		if Global.IpLocation, err = geoip2.FromBytes(reply.([]byte)); err != nil {
			logger.AccessLogger.Errorln("Error opening IP2Location database:", err)
			return
		}
		logger.AccessLogger.Infoln("加载IP库成功...")
	} else {
		logger.AccessLogger.Warnln("加载IP库失败,未找到IP库")
		err = errors.New("加载IP库失败,未找到IP库")
		return
	}
	return
}

func GetIpStore(url string) (err error) {

	logger.AccessLogger.Infoln("开始获取IP库数据...")

	conn := redis.RPool.Get()

	defer func() {
		if err1 := conn.Close(); err1 != nil {
			logger.ErrorLogger.Infoln(err1.Error())
			err = err1
		} else {
			_ = LoadIpStore()
		}
	}()

	req := http.New(
		http.WithUrl(url),
		http.WithMethod(http.GET),
	)
	if err = req.Do(); err != nil {
		logger.AccessLogger.Errorln("获取远端IP失败:", err.Error())
		return
	}
	if err = conn.Send("SET", IpStoreKey, req.Result); err != nil {
		logger.AccessLogger.Errorln("获取远端IP失败:", err.Error())
		return
	}
	if err = conn.Flush(); err != nil {
		logger.AccessLogger.Errorln("获取远端IP失败:", err.Error())
		return
	}
	logger.AccessLogger.Infoln("IP库数据获取完毕...")

	return
}

func GetIpAddress(ip string) string {

	defer func() {
		err := recover()
		if err != nil {
			buf := make([]byte, 1<<16)
			runtime.Stack(buf, true)
			e := reflect.ValueOf(err)
			logger.AccessLogger.Errorln(e.String())
		}
	}()

	if len(ip) > 0 && Global.IpLocation != nil {
		// 查询 IP 地址信息
		record, err := Global.IpLocation.City(net.ParseIP(ip))
		if err != nil {
			return ""
		}
		return fmt.Sprintf("%s %s", record.Country.Names["zh-CN"], record.City.Names["zh-CN"])
	}
	return ""
}