package common

import (
	"math"
	"strconv"
	"strings"
)

// MoneyNegation 金额取反 负负得正
func MoneyNegation(s string) string {
	switch {
	case s == "":
		return s
	case s[0] == '-':
		return s[1:]
	default:
		return "-" + s
	}
}

// IsAmountEqual 判断两个金额字符串是否相等
func IsAmountEqual(amount1, amount2 string) bool {
	// 规范化金额字符串
	normalizedAmount1 := normalizeAmount(amount1)
	normalizedAmount2 := normalizeAmount(amount2)
	if normalizedAmount1 == "" {
		normalizedAmount1 = "0"
	}
	if normalizedAmount2 == "" {
		normalizedAmount2 = "0"
	}

	// 转换为浮点数进行比较
	value1, err1 := strconv.ParseFloat(normalizedAmount1, 64)
	value2, err2 := strconv.ParseFloat(normalizedAmount2, 64)

	// 如果任意一个转换失败，则认为不相等
	if err1 != nil || err2 != nil {
		return false
	}

	// 比较浮点数
	return math.Abs(value2-value1) < 0.0001
}

// normalizeAmount 规范化金额字符串
func normalizeAmount(amount string) string {
	// 去掉逗号和多余的空格
	return strings.ReplaceAll(strings.TrimSpace(amount), ",", "")
}

// MoneyNormalize 金额标准化 "1,234.56" -> "1234.56"
func MoneyNormalize(s string) string {
	return strings.ReplaceAll(s, ",", "")
}

// 金额字符串求和，要求金额字符串必须是整数且保留两位小数。
func MoneyAdd(a, b string) string {
	// n = max(len(a), len(b))
	var n int
	if len(a) > len(b) {
		n = len(a)
	} else {
		n = len(b)
	}

	// 倒序求和
	//  123.45
	// + 67.89
	// --------
	// _191.34
	bs := make([]byte, n+1) // 可能有进位
	var carry byte
	for i := 1; i <= n; i++ {
		// 小数点
		if i == 3 {
			bs[n-i+1] = '.'
			continue
		}

		// 和 算数值
		c := byteOf(a, i) + byteOf(b, i) + carry
		if c >= 10 {
			carry = 1
			c -= 10
		} else {
			carry = 0
		}
		bs[n-i+1] = c + '0'
	}
	if carry != 0 {
		bs[0] = '1'
		return string(bs)
	}
	return string(bs[1:])
}

// 倒取字符串对应位算数值，超长取 0。
//
//	byteOf("123.45", 1) -> 5
//	byteOf("67.89", 5) -> 0
func byteOf(s string, i int) byte {
	if len(s) < i {
		return 0
	}
	return s[len(s)-i] - '0'
}
