package gio

import (
	"fmt"
	"io"
	"reflect"
	"runtime"
	"strings"
)

func ReadLimit(r io.Reader, n int64) ([]byte, error) {
	if n == 0 {
		n = 4096
	}
	return io.ReadAll(io.LimitReader(r, n))
}

func CallFuncName(skip int) string {
	pc, _, _, _ := runtime.Caller(skip + 1)
	funcName := runtime.FuncForPC(pc).Name()
	return funcName[strings.LastIndex(funcName, ".")+1:]
}

func StructToMap(obj any) (map[string]any, error) {
	// 获取反射值
	val := reflect.ValueOf(obj)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}

	// 确保输入是结构体
	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("input must be a struct or struct pointer")
	}

	// 创建结果 map
	result := make(map[string]any)
	typ := val.Type()

	// 遍历结构体的字段
	for i := 0; i < val.NumField(); i++ {
		field := typ.Field(i)
		fieldVal := val.Field(i)

		// 获取 json 标签
		jsonTag := field.Tag.Get("json")
		if jsonTag == "" {
			jsonTag = field.Name
		} else {
			if idx := strings.Index(jsonTag, ","); idx != -1 {
				jsonTag = jsonTag[:idx]
			}
		}

		// 跳过忽略字段或无效字段
		if jsonTag == "-" || !fieldVal.IsValid() {
			continue
		}

		// 检查字段是否为结构体或结构体指针，且是否有 json 标签
		hasJsonTag := field.Tag.Get("json") != ""
		if (fieldVal.Kind() == reflect.Struct || (fieldVal.Kind() == reflect.Ptr && !fieldVal.IsNil() && fieldVal.Elem().Kind() == reflect.Struct)) && !hasJsonTag {
			// 如果是结构体且无 json 标签，递归展开
			var nestedVal interface{}
			if fieldVal.Kind() == reflect.Ptr {
				nestedVal = fieldVal.Interface()
			} else {
				nestedVal = fieldVal.Interface()
			}
			nestedMap, err := StructToMap(nestedVal)
			if err != nil {
				return nil, err
			}
			for k, v := range nestedMap {
				result[k] = v
			}
		} else {
			// 其他情况（包括有 json 标签的嵌套结构体），直接存储字段值
			result[jsonTag] = fieldVal.Interface()
		}
	}

	return result, nil
}

func Equal(a, b any) bool {
	if a == nil && b == nil {
		return true
	}
	if a == nil || b == nil {
		return false
	}
	return reflect.DeepEqual(a, b)
}
