/*

 Copyright (c) [2023] [pcm]
 [pcm-coordinator] is licensed under Mulan PSL v2.
 You can use this software according to the terms and conditions of the Mulan PSL v2.
 You may obtain a copy of Mulan PSL v2 at:
          http://license.coscl.org.cn/MulanPSL2
 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 See the Mulan PSL v2 for more details.

*/

package common

import (
	"encoding/json"
	"fmt"
	"github.com/go-resty/resty/v2"
	"math"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// 求交集
func Intersect(slice1, slice2 []int64) []int64 {
	m := make(map[int64]int)
	nn := make([]int64, 0)
	for _, v := range slice1 {
		m[v]++
	}

	for _, v := range slice2 {
		times, _ := m[v]
		if times == 1 {
			nn = append(nn, v)
		}
	}
	return nn
}

func IntersectString(slice1, slice2 []string) []string {
	k := make(map[string]int)
	for _, num := range slice1 {
		k[num]++
	}
	var output []string
	for _, num := range slice2 {
		if k[num] > 0 {
			output = append(output, num)
			k[num]--
		}
	}
	return output
}

func RemoveDuplicates(slc []string) []string {
	keys := make(map[string]bool)
	list := []string{}

	for _, entry := range slc {
		if _, value := keys[entry]; !value {
			keys[entry] = true
			list = append(list, entry)
		}
	}
	return list
}

func MicsSlice(origin []int64, count int) []int64 {
	tmpOrigin := make([]int64, len(origin))
	copy(tmpOrigin, origin)
	//一定要seed
	rand.Seed(time.Now().Unix())
	rand.Shuffle(len(tmpOrigin), func(i int, j int) {
		tmpOrigin[i], tmpOrigin[j] = tmpOrigin[j], tmpOrigin[i]
	})

	result := make([]int64, 0, count)
	for index, value := range tmpOrigin {
		if index == count {
			break
		}
		result = append(result, value)
	}
	return result
}

func RoundFloat(val float64, precision uint) float64 {
	ratio := math.Pow(10, float64(precision))
	return math.Round(val*ratio) / ratio
}

func Contains(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func ConcatMultipleSlices[T any](slices [][]T) []T {
	var totalLen int

	for _, s := range slices {
		totalLen += len(s)
	}

	result := make([]T, totalLen)

	var i int

	for _, s := range slices {
		i += copy(result[i:], s)
	}

	return result
}

func GetRestyRequest(timeoutSeconds int64) *resty.Request {
	client := resty.New().SetTimeout(time.Duration(timeoutSeconds) * time.Second)
	request := client.R()
	return request
}

func Unique(s []string) []string {
	inResult := make(map[string]bool)
	var result []string
	for _, str := range s {
		if _, ok := inResult[str]; !ok {
			inResult[str] = true
			result = append(result, str)
		}
	}
	return result
}

func ConvertTypeToString(v interface{}) string {
	switch v.(type) {

	case int:
		s := v.(int)
		return strconv.Itoa(s)
	case string:
		s := v.(string)
		return s
	case float64:
		s := strconv.FormatFloat(v.(float64), 'f', -1, 64)
		return s
	case int64:
		s := v.(int64)
		return strconv.FormatInt(s, 64)
	case json.Number:
		return v.(json.Number).String()
	default:
		return ""
	}
}

func GetJSONTag(structObj interface{}, fieldName string) (string, error) {
	// 获取结构体的反射类型
	t := reflect.TypeOf(structObj)

	// 确保传入的是结构体
	if t.Kind() != reflect.Struct {
		return "", fmt.Errorf("expected a struct, got %T", structObj)
	}

	// 查找字段
	field, found := t.FieldByName(fieldName)
	if !found {
		return "", fmt.Errorf("field '%s' not found", fieldName)
	}

	// 获取 `json` 标签
	jsonTag := field.Tag.Get("json")
	if jsonTag == "" {
		return field.Name, nil // 默认使用字段名（小写）
	}

	// 去掉可能的 `omitempty` 等选项
	return strings.Split(jsonTag, ",")[0], nil
}
