package security

import (
	"fmt"
	"strings"

	"github.com/fiskerinc/cloud-services/pkg/redis"
	"github.com/fiskerinc/cloud-services/pkg/utils/envtool"

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

func NewSalter(auth string) (ISalter, error) {
	var encryptor IEncryptor

	key := []byte(envtool.GetEnv("MASTER_KEY", "REPLACE_ME_REPLACE_ME_REPLACE_ME"))
	byteAuth := []byte(auth)
	nonce := []byte(envtool.GetEnv("MASTER_KEY_NONCE", "_REPLACE_ME_"))

	encryptor, _, err := NewEncryptor(key, byteAuth, nonce)
	return &Salter{encryptor: encryptor, auth: auth}, err
}

type ISalter interface {
	GenerateSessionID(string, string) string
	ValidateSessionID(string) error
	CheckSessionID(redis.Client, string) error
}

type Salter struct {
	encryptor IEncryptor
	auth      string
}

func (s *Salter) GenerateSessionID(key string, salt string) string {
	return s.encryptor.EncryptStringToBase64(fmt.Sprintf("%s:%s", key, salt))
}

func (s *Salter) ValidateSessionID(sessionID string) error {
	if sessionID == "" {
		return ErrInvalidSessionID
	}
	data, err := s.encryptor.DecryptBase64ToString(sessionID)
	if err != nil {
		return err
	}

	vin := strings.Split(data, ":")[0]
	if vin != s.auth {
		return ErrInvalidSessionID
	}

	return nil
}

func (s *Salter) CheckSessionID(client redis.Client, vin string) error {
	sessionID, err := redigo.String(client.Get(redis.HMISessionKey(vin)))
	if err != nil {
		return errors.WithStack(err)
	}
	err = s.ValidateSessionID(sessionID)
	if err != nil {
		return err
	}
	return nil
}
