package redis

import (
	"fmt"

	"runtime/debug"

	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/google/uuid"
)

const (
	channelPrefix = "channel"

	SupersetAccTokenKey = "superset:access_token"
)

// ChannelKey provides hash value for redis channel
func ChannelKey(id string) string {
	return fmt.Sprintf("%s:%s", channelPrefix, id)
}

// ParseChannelKey returns id from hash value
func ParseChannelKey(key string) string {
	return key[len(channelPrefix)+1:]
}

const queuePrefix = "queue"

// QueueKey provides hash value for redis queue
func QueueKey(id string) string {
	if id == "" {
		stack := debug.Stack()
		logger.Warn().Str("Queue", queuePrefix).Str("ID", id).Str("Stack", string(stack)).Msg("Creating Redis Queue Key Empty")

	}
	return fmt.Sprintf("%s:%s", queuePrefix, id)
}

// ParseQueueKey returns id from hash value
func ParseQueueKey(key string) string {
	return key[len(queuePrefix)+1:]
}

func CarConfigKey(vin string) string {
	return fmt.Sprintf("car:%s:config", vin)
}

func CarLogFilter(vin string) string {
	return fmt.Sprintf("car:%s:state:log", vin)
}

// WindowsHashKey provides hash key lookup string for windows state
func WindowsHashKey(vin string) string {
	return fmt.Sprintf("car:%s:state:windows", vin)
}

// CarStateHashKey provides hash key structure for car state
//
//	car state values such as windows, locks, etc. are stored as
//	keys in the redis hash map
func CarStateHashKey(vin string) string {
	return fmt.Sprintf("car:%s:state", vin)
}

// CarAlerts returns key of expiring cache of sent car alerts.
func CarAlerts(vin string) string {
	return fmt.Sprintf("car:%s:alerts", vin)
}

// CANParseSignalWarnings returns key of expiring cache of unknown signals.
func CANParseSignalWarnings(version string) string {
	return fmt.Sprintf("can:version:%s:signals:warn", version)
}

// CarToDriverKey provides hash key lookup for driver associated with car
func CarToDriverKey(vin string, id string) string {
	return fmt.Sprintf("car:%s:driver:%s", vin, id)
}

// CarToAllDriversKey provides hash key lookup for drivers associated with car
func CarToAllDriversKey(vin string) string {
	return fmt.Sprintf("car:%s:drivers", vin)
}

// CarSessionsKey provides a set of all cars in session
func CarSessionsKey() string {
	return "cars:sessions"
}

func CarLocationsKey() string {
	return "cars:locations"
}

// CarUpdateStatusHashKey provides hash key lookup string for UpdateStatus
func CarUpdateStatusHashKey(carupdateid int64) string {
	return fmt.Sprintf("carupdate:%v", carupdateid)
}

// CarUpdateStatusHMIHashKey provides hash key lookup string for UpdateStatus
func CarUpdateStatusTBOXHashKey(carupdateid int64) string {
	return fmt.Sprintf("carupdatetbox:%v", carupdateid)
}

// CarUpdateStatusHMIHashKey provides hash key lookup string for UpdateStatus
func CarUpdateStatusHMIHashKey(carupdateid int64) string {
	return fmt.Sprintf("carupdatehmi:%v", carupdateid)
}

func DriverToVINsKey(id string) string {
	return fmt.Sprintf("driver:%s:cars", id)
}

// HMISessionsKey provides a set of all HMIs in session
func HMISessionsKey() string {
	return "hmi:sessions"
}

// HMIManySessionsKey provides a set of all sessions cloud believes are open
func HMIManySessionsKey(vin string) string {
	return fmt.Sprintf("hmi:%s:many-sessions", vin)
}

// HMISessionKey provides hash key lookup for HMI session key
func HMISessionKey(vin string) string {
	return fmt.Sprintf("hmi:%s:session", vin)
}

func HMISaltKey(vin string) string {
	return fmt.Sprintf("hmi:%s:salt", vin)
}

// FileIDEncryptionParamsKey provides hash key lookup string for file encryption parameters
func FileIDEncryptionParamsKey(fileid string) string {
	return fmt.Sprintf("fileid:%s", fileid)
}

// MobileSessionsKey provides a set of all mobiles in session
func MobileSessionsKey() string {
	return "mobile:sessions"
}

// APITokenKey provides hash key lookup string
func APITokenKey(key string) string {
	return fmt.Sprintf("apikey:%s", key)
}

func SubscriptionTypeListKey(subtypeID uuid.UUID) string {
	return fmt.Sprintf("subscriptiontypes:%s", subtypeID.String())
}

// TimezoneQuadKey provides hash key lookup string
func TimezoneQuadKey(quadkey string, zoom int) string {
	trim := min(len(quadkey), zoom)
	return fmt.Sprintf("timezone:%s", quadkey[:trim])
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
