package strconv

import (
	"reflect"
	"strconv"

	"github.com/pingcap/errors"
	"golang.org/x/exp/constraints"
)

var IntegerTypeNameToBitSize = map[string]int{
	"uint64": 64,
	"uint32": 32,
	"uint16": 16,
	"uint8":  8,
	"uint":   0,
	"int64":  64,
	"int32":  32,
	"int16":  16,
	"int8":   8,
	"int":    0,
}

// ToInteger converts a string to an integer.
func ToInteger[T constraints.Integer](s string, base int) (T, error) {
	var x T
	switch any(x).(type) {
	case uint64, uint32, uint16, uint8, uint:
		v, err := strconv.ParseUint(s, base, IntegerTypeNameToBitSize[reflect.TypeOf(x).String()])
		if err != nil {
			return x, err
		}
		return T(v), nil
	case int64, int32, int16, int8, int:
		v, err := strconv.ParseInt(s, base, IntegerTypeNameToBitSize[reflect.TypeOf(x).String()])
		if err != nil {
			return x, err
		}
		return T(v), err
	default:
		return x, errors.Errorf("type %s is not supported in ToInteger", reflect.TypeOf(x).String())
	}
}
