package ii

import (
	"errors"
	"fmt"
	"math"
	"reflect"
	"runtime"
	"strings"

	"git.simanc.com/software/golib/v4/features/mo"
)

var (
	errNil = errors.New("<nil>")
)

func getCallerName() string {
	pc, _, _, _ := runtime.Caller(2)
	return runtime.FuncForPC(pc).Name()
}

func valueType(v any) string {
	if v == nil {
		return errNil.Error()
	}
	return reflect.ValueOf(v).Type().String()
}

func toFloat64Decimal(f float64, decimal int) float64 {
	if decimal <= 0 {
		return f
	}
	float := math.Pow(10, float64(decimal))
	return math.Round(f*float) / float
}

func indexEqual(str, prefix, suffix string) bool {
	return strings.Index(str, prefix) == 0 && strings.LastIndex(str, suffix) == len(str)-1
}

func covertArray(field *FieldInfo, value any, target *mo.A, idx int) error {
	switch field.Items {
	case FieldItemsDefault, FieldItemsArray:
		(*target)[idx] = value
	case FieldItemsObject:
		obj, err := field.convertObject(value)
		if err != nil {
			return errCovertRetErr(field, value, err)
		}
		(*target)[idx] = obj
	case FieldItemsObjectId:
		oid, err := field.convertObjectID(value)
		if err != nil {
			return errCovertRetErr(field, value, err)
		}
		(*target)[idx] = oid
	default:
		return fmt.Errorf("convertArray: unsupported Items: %s", field.Items)
	}
	return nil
}

// fieldEnableType 启用的数据类型
// MongoDB 数据类型众多, 并非所有类型都适用于实际开发环境, 特在此处添加已启用的类型. 使用未启用的类型时会在 Unmarshal 时报错
var (
	fieldEnableType = map[mo.Type]struct{}{
		mo.TypeDouble:   {},
		mo.TypeString:   {},
		mo.TypeObject:   {},
		mo.TypeArray:    {},
		mo.TypeObjectId: {},
		mo.TypeBoolean:  {},
		mo.TypeDateTime: {},
		mo.TypeInt64:    {},
	}
)

// SetEnableType 启用 fieldEnableType 内未添加的类型
func SetEnableType(t mo.Type) {
	fieldEnableType[t] = struct{}{}
}

func isEnabledType(t mo.Type) bool {
	_, ok := fieldEnableType[t]
	return ok
}

var (
	// internalField 内部字段
	internalField = map[string]FieldInfo{
		ID:           idInfo,
		Creator:      creatorInfo,
		CreationTime: creationTimeInfo,
	}
)

var (
	idInfo = FieldInfo{
		Name:     ID,
		Type:     mo.TypeObjectId,
		Required: true,
		Unique:   true,
		Label:    ID,
		Default:  internalNew,
	}
	creatorInfo = FieldInfo{
		Name:     Creator,
		Type:     mo.TypeObjectId,
		Required: true,
		Unique:   false,
		Label:    "创建人",
	}
	creationTimeInfo = FieldInfo{
		Name:     CreationTime,
		Type:     mo.TypeDateTime,
		Required: true,
		Unique:   false,
		Label:    "创建时间",
		Default:  internalNow,
	}
)
