package utils

import (
	"encoding/json"
	"reflect"
	"strconv"
)

func If_to_int32(v interface{}, def int32) int32 {
	switch v.(type) {
	case string:
		i, err := strconv.ParseInt(v.(string), 10, 32)
		if err != nil {
			return def
		}
		return int32(i)
	case float32, float64:
		return int32(reflect.ValueOf(v).Float())
	case int, int8, int16, int32, int64:
		return int32(reflect.ValueOf(v).Int())
	case uint, uint8, uint16, uint32, uint64:
		return int32(reflect.ValueOf(v).Uint())
	case json.Number:
		if val, ok := v.(json.Number); ok {
			int64val, err := val.Int64()
			if err == nil {
				return int32(int64val)
			}
		}
		return 0
	default:
		return def
	}
}

func If_to_int64(v interface{}, def int64) int64 {
	switch v.(type) {
	case string:
		i, err := strconv.ParseInt(v.(string), 10, 64)
		if err != nil {
			return def
		}
		return i
	case float32, float64:
		return int64(reflect.ValueOf(v).Float())
	case int, int8, int16, int32, int64:
		return int64(reflect.ValueOf(v).Int())
	case uint, uint8, uint16, uint32, uint64:
		return int64(reflect.ValueOf(v).Uint())
	case json.Number:
		if val, ok := v.(json.Number); ok {
			int64val, err := val.Int64()
			if err == nil {
				return int64val
			}
		}
		return 0
	default:
		return def
	}
}

func If_to_uint64(v interface{}, def uint64) uint64 {
	switch v.(type) {
	case string:
		i, err := strconv.ParseInt(v.(string), 10, 64)
		if err != nil {
			return def
		}
		return uint64(i)
	case float32, float64:
		return uint64(reflect.ValueOf(v).Float())
	case int, int8, int16, int32, int64:
		return uint64(reflect.ValueOf(v).Int())
	case uint, uint8, uint16, uint32, uint64:
		return uint64(reflect.ValueOf(v).Uint())
	case json.Number:
		if val, ok := v.(json.Number); ok {
			int64val, err := val.Int64()
			if err == nil {
				return uint64(int64val)
			}
		}
		return 0
	default:
		return def
	}
}

func If_to_string(v interface{}, def string) string {
	switch v.(type) {
	case string:
		return v.(string)
	case float32, float64:
		return strconv.FormatFloat(float64(reflect.ValueOf(v).Float()), 'f', -1, 64)
	case int, int8, int16, int32, int64:
		return strconv.FormatInt(int64(reflect.ValueOf(v).Int()), 10)
	case uint, uint8, uint16, uint32, uint64:
		return strconv.FormatUint(uint64(reflect.ValueOf(v).Uint()), 10)
	default:
		return def
	}
}
