package convhelper

import (
	"fmt"
	"strconv"
	"time"

	"gorm.io/gorm"
)

const StandartDateTimeFormat = "2006-01-02 15:04:05"

// check string pointer, if nil return default value
func StrConvDefault(f *string, def string) string {
	if f == nil {
		return def
	}
	return *f
}

// check string pointer, if nil return empty string
func StrConvEmpty(f *string) string {
	return StrConvDefault(f, "-")
}

func ByteConvStr(f *byte) string {
	if f != nil {
		return strconv.Itoa(int(*f))
	}
	return ""
}

func Float32Conv(f *float32) float32 {
	if f == nil {
		return 0
	}
	return *f
}

func StrRelConv(b bool, d string) string {
	if b {
		return d
	} else {
		return ""
	}
}

func UintToString(f interface{}) *string {
	if f == nil {
		return nil
	}

	var t string
	switch v := f.(type) {
	case uint:
		t = strconv.FormatUint(uint64(v), 10)
	case uint8:
		t = strconv.FormatUint(uint64(v), 10)
	case uint16:
		t = strconv.FormatUint(uint64(v), 10)
	case uint32:
		t = strconv.FormatUint(uint64(v), 10)
	case uint64:
		t = strconv.FormatUint(v, 10)
		// Handle pointer types
	case *uint:
		if v != nil {
			t = strconv.FormatUint(uint64(*v), 10)
		}
	case *uint8:
		if v != nil {
			t = strconv.FormatUint(uint64(*v), 10)
		}
	case *uint16:
		if v != nil {
			t = strconv.FormatUint(uint64(*v), 10)
		}
	case *uint32:
		if v != nil {
			t = strconv.FormatUint(uint64(*v), 10)
		}
	case *uint64:
		if v != nil {
			t = strconv.FormatUint(*v, 10)
		}
	default:
		return nil // Unsupported type
	}

	return &t
}

func BoolToString(f *bool) *string {
	if f == nil {
		return nil
	}
	t := strconv.FormatBool(*f)
	return &t
}

// Handling gorm.DeletedAt
func DeletedAtToString(deletedAt *gorm.DeletedAt) *string {
	if deletedAt == nil || !deletedAt.Valid {
		return nil
	}
	return TimeToStringWithFormat(&deletedAt.Time, "")
}

func BoolToFloat64(b bool) float64 {
	if b {
		return 1.0
	}
	return 0.0
}

func Float64ToBool(f float64) bool {
	return f == 1.0
}

func StringToBool(s string) bool {
	return s == "1"
}

func StringToFloat32(s string) float32 {
	f, _ := strconv.ParseFloat(s, 32)
	return float32(f)
}

func StringToFloat64(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}

func Float64ToString(f float64) string {
	return fmt.Sprintf("%.2f", f)
}

func StringToUint64(s string) *uint64 {
	if s == "" {
		return nil
	}
	u, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		return nil
	}
	return &u
}

func TimeToStringWithFormat(t *time.Time, format string) *string {
	result := ""
	if t == nil || t.IsZero() {
		return &result
	}

	if format == "" {
		format = StandartDateTimeFormat
	}

	result = t.Format(format)
	return &result
}
