package utils

import (
	"errors"
	"strconv"
)

func OptionalBool(input *bool) bool {
	if input == nil {
		return false
	}

	return *input
}

func CreateOptionalBool(input bool) *bool {
	if input == false {
		return nil
	}

	return &input
}

func OptionalString(input *string) string {
	if input == nil {
		return ""
	}

	return *input
}

func OptionalInt(input *int) int {
	if input == nil {
		return 0
	}

	return *input
}

// Zero values become nil; the inverse of OptionalInt.
func CreateOptionalInt(input int) *int {
	if input == 0 {
		return nil
	}

	return &input
}

// Empty string becomes nil; the inverse of OptionalString.
func CreateOptionalString(input string) *string {
	if input == "" {
		return nil
	}

	return &input
}

// Returns an error if input contains non-digit characters or parses to <= 0.
func GetNumberFromString(input string) (int, error) {
	for _, c := range input {
		if c < '0' || c > '9' {
			return 0, errors.New("invalid input")
		}
	}

	idAsInt, err := strconv.Atoi(input)
	if err != nil || idAsInt <= 0 {
		return 0, errors.New("invalid input")
	}

	return idAsInt, nil
}

type Number interface {
	int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}

func OptionalNumber[T Number](input *T) T {
	if input == nil {
		return 0
	}

	return *input
}

// Zero values become nil; the inverse of OptionalNumber.
func CreateOptionalNumber[T Number](input T) *T {
	if input == 0 {
		return nil
	}

	return &input
}

func IntToInt64Pointer(input *int) *int64 {
	if input == nil {
		return nil
	}
	val := int64(*input)
	return &val
}

func NumberToNumberPointer[T Number, Y Number](input *T) *Y {
	if input == nil {
		return nil
	}

	val := Y(*input)
	return &val
}
