package queries

import (
	"github.com/fiskerinc/cloud-services/pkg/common"
	s "github.com/fiskerinc/cloud-services/pkg/security"
	"github.com/go-pg/pg/v10/orm"
	"github.com/pkg/errors"
)

type SymKeysInterface interface {
	Insert(keys common.SymKeys) (orm.Result, error)
	SelectAll() ([]common.SymKeys, error)
	SelectByVIN(vin string) (common.SymKeys, error)
}

type SymKeys struct {
	QueryBase
}

func (sk *SymKeys) Insert(keys common.SymKeys) (orm.Result, error) {
	enc := s.Encrypt{}
	encryptor, err := enc.GetEncryptor()
	if err != nil {
		return nil, err
	}
	keys.SecOC.SetBytes(encryptor.EncryptChunk(keys.SecOC.Bytes()))
	keys.SecureLogging.SetBytes(encryptor.EncryptChunk(keys.SecureLogging.Bytes()))
	keys.SecureStorage.SetBytes(encryptor.EncryptChunk(keys.SecureStorage.Bytes()))

	return sk.GetDBConn().Model(&keys).Insert()
}

func (sk *SymKeys) SelectAll() ([]common.SymKeys, error) {
	symkeys := []common.SymKeys{}

	err := sk.GetDBConn().Model(&symkeys).Select()
	if err != nil {
		return nil, errors.WithStack(err)
	}

	for i := range symkeys {
		err = sk.decrypt(&symkeys[i])
		if err != nil {
			return nil, err
		}
	}
	return symkeys, err
}

func (sk *SymKeys) SelectByVIN(vin string) (common.SymKeys, error) {
	symkey := common.SymKeys{}

	err := sk.GetDBConn().Model(&symkey).Where("vin = ?", vin).Select()
	if err != nil {
		return symkey, errors.WithStack(err)
	}

	err = sk.decrypt(&symkey)
	return symkey, err
}

func (sk *SymKeys) decrypt(symkeys *common.SymKeys) error {
	enc := s.Encrypt{}
	encryptor, err := enc.GetEncryptor()
	if err != nil {
		return err
	}

	secoc, err := encryptor.DecryptChunk(symkeys.SecOC.Bytes())
	if err != nil {
		return err
	}
	symkeys.SecOC.SetBytes(secoc)

	logging, err := encryptor.DecryptChunk(symkeys.SecureLogging.Bytes())
	if err != nil {
		return err
	}
	symkeys.SecureLogging.SetBytes(logging)

	storage, err := encryptor.DecryptChunk(symkeys.SecureStorage.Bytes())
	if err != nil {
		return err
	}
	symkeys.SecureStorage.SetBytes(storage)

	return nil
}
