package utils

import (
	"fmt"
	"github.com/UpmeshLTD/urus-aio/infrastructure/enums"
	"math/rand"
	"regexp"
	"strings"
	"time"

	"github.com/UpmeshLTD/urus-aio/infrastructure/db/entities"
	"github.com/google/uuid"
	"github.com/segmentio/ksuid"
)

func RandomString(n int) string {
	rand.Seed(time.Now().UnixNano())

	var letter = []rune("abcdefghijklmnopqrstuvwxyz0123456789")

	b := make([]rune, n)
	for i := range b {
		b[i] = letter[rand.Intn(len(letter))]
	}
	return string(b)
}

func ConvertDBLikeString(value string) string {
	return "%" + value + "%"
}

func HidePhoneNumber(str string) string {
	n := len(str)
	if m := regexp.MustCompile(`^(\d{3})(\d+)(\d{3})$`).FindStringSubmatch(str); len(m) > 3 {
		return m[1] + strings.Repeat("*", len(m[2])) + m[3]
	}
	if n > 3 {
		return strings.Repeat("*", n-3) + str[n-3:n]
	}
	return str
}

func ConvertAcceptLanguageToCountryID(lang string) int64 {
	if v, ok := entities.LanguageCountryIDMap[strings.ToLower(lang)]; ok {
		return v
	}
	return 0
}

func GenerateCode(prefix string) string {
	s := strings.Replace(uuid.NewString(), "-", "", -1)
	return fmt.Sprintf("%s%d%s", prefix, time.Now().Unix(), strings.ToUpper(s[:6]))
}

func GenerateNumber() string {
	return fmt.Sprintf("%d%04d", time.Now().UnixMicro(), rand.Intn(9999))
}

func FixAcceptLanguage(language string) string {
	language = strings.ToLower(language)
	if v, ok := entities.AcceptLanguageMap[language]; ok {
		return v
	}
	return language
}

func RemovePrefixPhoneNumber(str string) string {
	if str == "" {
		return ""
	}
	str = strings.Trim(str, "+")
	if len(str) > 2 {
		return "0" + str[2:]
	}
	return "0" + str
}

func InTimeSpan(start, end, check time.Time) bool {
	return !(check.Before(start) || check.After(end))
}

/*
IsTimeBetween
startTimeOfDayLayout: 09:00:00
endTimeOfDayLayout: 18:00:00
*/
func IsTimeBetween(t time.Time, startTimeOfDayLayout string, endTimeOfDayLayout string) bool {
	dateLayout := "2006-01-02"
	date := t.Format(dateLayout)
	t1, _ := time.ParseInLocation(enums.TimeFormatYMDHIS, date+" "+startTimeOfDayLayout, t.Location())
	t2, _ := time.ParseInLocation(enums.TimeFormatYMDHIS, date+" "+endTimeOfDayLayout, t.Location())
	fmt.Printf("[IsTimeBetween] Client Time (%s): %s\n", t.Location().String(), t)
	fmt.Printf("[IsTimeBetween] T1 Time: %s\n", t1)
	fmt.Printf("[IsTimeBetween] T2 Time: %s\n", t2)
	return InTimeSpan(t1, t2, t)
}

func IsTimeBetween9AMTo6PM(t time.Time) bool {
	return IsTimeBetween(t, "09:00:00", "18:00:00")
}

func IsTimeOnWeekday(t time.Time, days []string) bool {
	return InArray(t.Format("Mon"), days)
}

func IsTimeOnSaturday(t time.Time) bool {
	return IsTimeOnWeekday(t, []string{"Sat"})
}

func IsTimeOnSunday(t time.Time) bool {
	return IsTimeOnWeekday(t, []string{"Sun"})
}

func InArray(s string, a []string) bool {
	for _, v := range a {
		if v == s {
			return true
		}
	}
	return false
}

func NewId(prefix string) string {
	return prefix + "_" + ksuid.New().String()
}

func IsEmpty(v *string) bool {
	return v == nil || *v == ""
}

func IsDigit(v string) bool {
	return regexp.MustCompile(`^[0-9]+$`).MatchString(v)
}

func ConvertRegionToCurrency(region string) string {
	region = strings.ToUpper(region)
	if v, ok := entities.RegionCurrencyMap[region]; ok {
		return v
	}
	return "USD"
}

func GenerateKeyFromCartIdAndShippingGroupId(cartId string, shippingGroupId *string) string {
	if shippingGroupId == nil || *shippingGroupId == "" {
		return cartId + "|-"
	}
	return cartId + "|" + *shippingGroupId
}

func String(s string) *string {
	return &s
}
