package util

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/bwmarrin/snowflake"
	"github.com/go-redis/redis"

	"tower_api/pkg/setting"
)

// CheckErr 检查错误
func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}

// CheckRedisErr 检查redis的错误
func CheckRedisErr(err error) {
	if err != nil && err != redis.Nil {
		panic(err)
	}
}

// EncodeMD5 md5加密
func EncodeMD5(value string) string {
	m := md5.New()
	m.Write([]byte(value))

	return hex.EncodeToString(m.Sum(nil))
}

// QuoteConversion 将双引号转化为单引号
func QuoteConversion(msg string) string {
	return strings.Replace(msg, "\"", "'", -1)
}

// F2I float转int类型
func F2I(f float64) int {
	i, _ := strconv.Atoi(fmt.Sprintf("%1.0f", f))
	return i
}

// Struct2Map 结构体转为map
func Struct2Map(obj interface{}) map[string]interface{} {
	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	var data = make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		data[string(t.Field(i).Tag.Get("json"))] = v.Field(i).Interface()
	}
	return data
}

// GetMapStrKeys 获取map的string key
func GetMapStrKeys(m map[string]interface{}) []string {
	keys := make([]string, 0, len(m))
	for k, _ := range m {
		keys = append(keys, k)
	}
	return keys
}

// GenSignMD5 生成md5签名
func GenSignMD5(m map[string]interface{}, secret string) string {
	keys := GetMapStrKeys(m)
	//排序
	sort.Strings(keys)
	//拼接成字符串
	tmpStr := ""
	for _, v := range keys {
		if v == "sign" {
			continue
		}
		tmpStr += fmt.Sprintf("%s=%v&", v, m[v])
	}
	tmpStr = strings.TrimRight(tmpStr, "&")
	tmpStr += secret
	//md5加密
	return EncodeMD5(tmpStr)
}

// Uint64Random 生成uint64的随机数
func Uint64Random(va11, val2 uint64) uint64 {
	node, _ := snowflake.NewNode(1)
	id := node.Generate().Int64()
	return uint64(id)
}

// IsOpenId 判断是否是openid
func IsOpenId(openid string) bool {
	if m, _ := regexp.MatchString(`^[_A-Za-z0-9\-]{1,40}$`, openid); !m {
		return false
	}
	return true
}

func IsNormalStr(str string) bool {
	if m, _ := regexp.MatchString(`^[_A-Za-z0-9\-]{1,40}$`, str); !m {
		return false
	}
	return true
}

// IsAppId 判断是否是appid
func IsAppId(appid string) bool {
	//抖音的appid不是wx开头的,这里做一下兼容就不需要修改业务逻辑
	if m, _ := regexp.MatchString(`^[_A-Za-z0-9\-]{1,40}$`, appid); !m {
		return false
	}
	return true
}

// Days 计算开始时间戳与结束时间戳的间隔多少天
func Days(timestampFrom, timestampTo int64) int {
	var midnightUnix = func(t time.Time) int64 {
		y, m, d := t.Date()
		return time.Date(y, m, d+1, 0, 0, 0, 0, time.Local).Unix()
	}

	var days = 0
	for {
		if midnightUnix(time.Unix(timestampFrom, 0).AddDate(0, 0, days)) >= timestampTo {
			days++
			break
		}
		days++
	}
	return days
}

// ParseJsonStr 公共解析json字符串
// jsonStr 字符串
// bind 需要绑定的对象(业务逻辑中要使用的话则传递指针结构体)
func ParseJsonStr(jsonStr string, bind interface{}) error {
	return json.Unmarshal([]byte(jsonStr), &bind)
}

func Ter[T any](cond bool, a, b T) T {
	if cond {
		return a
	}
	return b
}

func GetRunMod() string {
	return setting.Settings.Server.RunMode
}
