package utility

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/shopspring/decimal"
)

// Float64CutString 保留size位小数 不足则填充0
func Float64CutString(num float64, size int32) string {
	de := decimal.NewFromFloat(num).Truncate(size)
	return de.StringFixed(size)
}

func FloatAddCutFixStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2)).Truncate(size)
	return result.StringFixed(size)
}

// FloatCut 按保留的小数点位数,去掉多余的小数
func FloatCut(num float64, size int32) float64 {
	de := decimal.NewFromFloat(num)
	str := de.Truncate(size)
	result, _ := str.Float64()
	return result
}

// FloatCutStr 按保留的小数点位数,去掉多余的小数 非四舍五入
func FloatCutStr(num float64, size int32) string {
	if num == 0 {
		return `0`
	}
	de := decimal.NewFromFloat(num)
	str := de.Truncate(size)
	result := str.String()
	return result
}

// StringFloat64Cut 保留8为小数后边为0不截取
func StringFloat64Cut(num string, size int32) string {
	// 清理输入字符串，去除空字符和其他非数字字符
	if strings.Contains(num, "x00") {
		fmt.Sprintf("打印信息", num)
	}

	cleanedNum := strings.TrimRight(num, "\x00")                                         // 去除空字符
	cleanedNum = strings.TrimSpace(cleanedNum)                                           // 去除空格
	cleanedNum = strings.ReplaceAll(strings.ReplaceAll(cleanedNum, ",", ""), "\x00", "") // 去除逗号
	de, err := decimal.NewFromString(cleanedNum)
	if err != nil {
		return ""
	}
	return de.Truncate(size).String()
}

// StrToFloatCut 按保留的小数点位数,去掉多余的小数 非四舍五入
func StrToFloatCut(num string, size int32) float64 {
	if num == "" {
		return 0
	}
	de, _ := decimal.NewFromString(num)
	str := de.Truncate(size)
	result, _ := str.Float64()
	return result
}

// FloatThousand 对float进行千分位处理返回字符串,比如2568965463.256545 => 2,568,965,463.256545
func FloatThousand(num float64) string {
	if num <= 1000 {
		return decimal.NewFromFloat(num).String()
	}
	n := decimal.NewFromFloat(num).String()
	dec := ""
	if strings.Index(n, ".") != -1 {
		dec = n[strings.Index(n, ".")+1:]
		n = n[0:strings.Index(n, ".")]
	}
	for i := 0; i <= len(n); i = i + 4 {
		a := n[0 : len(n)-i]
		b := n[len(n)-i:]
		n = a + "," + b
	}
	if n[0:1] == "," {
		n = n[1:]
	}
	if n[len(n)-1:] == "," {
		n = n[0 : len(n)-1]
	}
	if dec != "" {
		n = n + "." + dec
	}
	return n
}

// Float8ToString 按保留的小数点8位数,去掉多余的小数, return string
func Float8ToString(num float64) string {
	return FloatToString(num, 8)
}

// FloatAdd float + float
func FloatAdd(num1, num2 float64) float64 {
	result := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
	f, _ := result.Float64()
	return f
}

func FloatAddCutStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
	return result.Truncate(size).String()
}

func FloatAddCut(num1, num2 float64, size int32) float64 {
	result := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
	f, _ := result.Truncate(size).Float64()
	return f
}

// FloatSub float - float
func FloatSub(num1, num2 float64) float64 {
	if num2 == 0 {
		return num1
	}
	result := decimal.NewFromFloat(num1).Sub(decimal.NewFromFloat(num2))
	f, _ := result.Float64()
	return f
}

// FloatSubCut float - float
func FloatSubCut(num1, num2 float64, size int32) float64 {
	if num2 == 0 {
		return num1
	}
	result := decimal.NewFromFloat(num1).Sub(decimal.NewFromFloat(num2))
	f, _ := result.Truncate(size).Float64()
	return f
}

// FloatSubCutStr float - float
func FloatSubCutStr(num1, num2 float64, size int32) string {
	if num2 == 0 {
		return decimal.NewFromFloat(num1).Truncate(size).String()
	}
	result := decimal.NewFromFloat(num1).Sub(decimal.NewFromFloat(num2))
	f := result.Truncate(size).String()
	return f
}

// FloatDiv float / float 两数相除
func FloatDiv(num1, num2 float64) float64 {
	result := decimal.NewFromFloat(num1).Div(decimal.NewFromFloat(num2))
	f, _ := result.Float64()
	return f
}

func FloatDivCutStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Div(decimal.NewFromFloat(num2))
	result = result.Truncate(size)
	s := result.String()
	return s
}

func FloatDivCutFixStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Div(decimal.NewFromFloat(num2))
	return result.Truncate(size).StringFixed(size)
}

func FloatDivCut(num1, num2 float64, size int32) float64 {
	result := decimal.NewFromFloat(num1).Div(decimal.NewFromFloat(num2))
	result = result.Truncate(size)
	f, _ := result.Float64()
	return f
}

// FloatMul float * float
func FloatMul(num1, num2 float64) float64 {
	result := decimal.NewFromFloat(num1).Mul(decimal.NewFromFloat(num2))
	f, _ := result.Float64()
	return f
}

// FloatMulCut  两数相乘并返回小数点后size位的float64
func FloatMulCut(num1, num2 float64, size int32) float64 {
	result := decimal.NewFromFloat(num1).Mul(decimal.NewFromFloat(num2))
	result = result.Truncate(size)
	f, _ := result.Float64()
	return f
}

// FloatMulCutStr float * float 两数相乘并返回指定小数位数的float64 返回字符串
func FloatMulCutStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Mul(decimal.NewFromFloat(num2))
	result = result.Truncate(size)
	return result.String()
}

// FloatMulCutFixStr float * float 两数相乘并返回指定小数位数的float64 返回字符串
func FloatMulCutFixStr(num1, num2 float64, size int32) string {
	result := decimal.NewFromFloat(num1).Mul(decimal.NewFromFloat(num2))
	result = result.Truncate(size)
	return result.StringFixed(size)
}

// GetTotalAmt 计算需要冻结的币  数量*??/价格
func GetTotalAmt(num int, price, contractVal float64, size int32) float64 {
	de := decimal.NewFromInt(int64(num)).
		Mul(decimal.NewFromFloat(contractVal)).
		Div(decimal.NewFromFloat(price)).
		Truncate(size)
	result2, _ := de.Float64()
	return result2
}

func GetNonce() string {
	s := strconv.FormatInt(time.Now().UnixNano(), 10)[0:11]
	return s
}

// IsEqual 比对2个float64 是否相等
func IsEqual(num1, num2 float64, size int32) bool {
	n1 := decimal.NewFromFloat(num1).Truncate(size)
	n2 := decimal.NewFromFloat(num2).Truncate(size)
	return n1.Equal(n2)
}

// GetDealAmt 根据下单张数，下单总的冻结金额，计算本次成交金额
func GetDealAmt(num, totalNum int, totalAmt float64, size int32) float64 {
	if num == totalNum {
		return totalAmt
	}
	de := decimal.NewFromFloat(totalAmt).
		Div(decimal.NewFromInt(int64(num))).
		Mul(decimal.NewFromInt(int64(num))).
		Truncate(size)

	result2, _ := de.Float64()
	return result2
}

func ToFloat64(v interface{}) float64 {
	if v == nil {
		return 0.0
	}

	switch v.(type) {
	case float64:
		return v.(float64)
	case string:
		vStr := v.(string)
		vF, _ := strconv.ParseFloat(vStr, 64)
		return vF
	default:
		panic("to float64 error.")
	}
}

func ToInt(v interface{}) int {
	if v == nil {
		return 0
	}

	switch v.(type) {
	case string:
		vStr := v.(string)
		vInt, _ := strconv.Atoi(vStr)
		return vInt
	case int:
		return v.(int)
	case float64:
		vF := v.(float64)
		return int(vF)
	default:
		panic("to int error.")
	}
}

func ToInt64(v interface{}) int64 {
	if v == nil {
		return 0
	}

	switch v.(type) {
	case float64:
		return int64(v.(float64))
	default:
		vv := fmt.Sprint(v)

		if vv == "" {
			return 0
		}

		vvv, err := strconv.ParseInt(vv, 0, 64)
		if err != nil {
			return 0
		}

		return vvv
	}
}
