package utils

import (
	"context"
	"crypto/ecdsa"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/oschwald/geoip2-golang"
	"hashrateNode/log"
	"math"
	"math/big"
	"net"
	"time"
)

// EarthRadius 地球半径（单位：千米）
const EarthRadius = 6371

// Coordinates 经纬度坐标结构体
type Coordinates struct {
	Latitude  float64 // 纬度
	Longitude float64 // 经度
}

// EthGetTransactionCount  获取账户nonce
func EthGetTransactionCount(client *ethclient.Client, param string) (uint64, error) {
	ctx := context.Background()
	addr := common.HexToAddress(param)
	nonce, err := client.NonceAt(ctx, addr, nil)
	return nonce, err
}

func GetTranOpts() (*bind.TransactOpts, error) {
	prv := beego.AppConfig.String("sendTranPrv")
	key, err := StringToPrivateKey(prv)
	if err != nil {
		return nil, err
	}
	chainID, _ := beego.AppConfig.Int64("chainID")
	auth, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(chainID))
	if err != nil {
		return nil, err
	}
	return auth, nil
}

// StringToPrivateKey 解析私钥
func StringToPrivateKey(privateKeyStr string) (*ecdsa.PrivateKey, error) {
	privateKeyByte, err := hexutil.Decode(privateKeyStr)
	if err != nil {
		return nil, err
	}
	privateKey, err := crypto.ToECDSA(privateKeyByte)
	if err != nil {
		return nil, err
	}
	return privateKey, nil
}

func Marshal(param interface{}) []byte {
	byteInfo, _ := json.Marshal(param)
	return byteInfo
}

func GetFormatTime(timestamp int64) string {
	return time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")
}

// 将角度转换为弧度
func degreesToRadians(degrees float64) float64 {
	return degrees * (math.Pi / 180.0)
}

func GetIpAddr(ipAddress string) *Coordinates {
	// 打开 MaxMind 的 GeoIP2 数据库文件
	db, err := geoip2.Open("GeoLite2-City.mmdb")
	if err != nil {
		log.Error(" geoip2 open error:", err)
		return nil
	}
	defer db.Close()
	// 解析 IP 地址
	ip := net.ParseIP(ipAddress)
	// 查询 IP 地址的位置信息
	record, err := db.City(ip)
	if err != nil {
		log.Error("Get ip city error:", err)
		return nil
	}
	// 打印经纬度信息
	fmt.Printf("IP地址: %s\n", ipAddress)
	fmt.Printf("经度: %f\n", record.Location.Longitude)
	fmt.Printf("纬度: %f\n", record.Location.Latitude)
	res := &Coordinates{
		Latitude:  record.Location.Latitude,
		Longitude: record.Location.Longitude,
	}
	return res
}

// CalculateDistance 计算两个经纬度坐标之间的距离（单位：千米）
func CalculateDistance(coord1, coord2 *Coordinates) float64 {
	lat1 := degreesToRadians(coord1.Latitude)
	lat2 := degreesToRadians(coord2.Latitude)
	lon1 := degreesToRadians(coord1.Longitude)
	lon2 := degreesToRadians(coord2.Longitude)
	// Haversine 公式
	dlon := lon2 - lon1
	dlat := lat2 - lat1
	a := math.Pow(math.Sin(dlat/2), 2) + math.Cos(lat1)*math.Cos(lat2)*math.Pow(math.Sin(dlon/2), 2)
	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
	distance := EarthRadius * c
	return distance
}
