package cache

import (
	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/db/queries"
	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/fiskerinc/cloud-services/pkg/redis"

	redigo "github.com/gomodule/redigo/redis"
	"github.com/pkg/errors"
)

// VerifyCarToDriver checks cache and DB for car to driver relationship.
// If relationship exists and not in cache, will cache value.
//
//	car:<VIN>:driver:<DRIVER_ID>
func VerifyCarToDriver(clientPool redis.ClientPoolInterface, db queries.CarsInterface, vin string, driverID string) (bool, error) {
	key := redis.CarToDriverKey(vin, driverID)

	ok, err := redisCheckGet(clientPool, key)
	if err != nil {
		return ok, err
	}

	if ok {
		return ok, err
	}

	carToDrivers, err := db.SelectCarToDriver(&common.CarToDriver{VIN: vin, DriverID: driverID})
	if err != nil {
		return false, err
	}
	verified := len(carToDrivers) == 1
	redisPlaceDriverCache(clientPool, key, verified)

	return verified, err
}

func redisCheckGet(clientPool redis.ClientPoolInterface, key string) (bool, error) {
	client := clientPool.GetFromPool()
	defer client.Close()
	ok, err := redigo.Bool(client.Execute("GET", key))
	if err != nil && !errors.Is(err, redigo.ErrNil) {
		logger.Warn().Err(err).Send()
		return ok, err
	}
	return ok, nil
}

func redisPlaceDriverCache(clientPool redis.ClientPoolInterface, key string, verified bool) (err error) {
	client := clientPool.GetFromPool()
	defer client.Close()
	batch := redis.NewRedisBatchCommands()
	batch.Add("SET", key, verified)
	batch.Add("EXPIRE", key, redisObjectExpire)
	_, err = client.ExecuteBatch(batch)
	return
}
