package token

import (
	"errors"
	"github.com/gogf/gf/database/gredis"
	"reflect"
	"sparrow/pkg/generator"
)

const (
	DeviceTokenKeyPrefix      = "device:token:"
	DeviceTokenExpires        = 7200
	ApplicationTokenKeyPrefix = "app:token:"
	ApplicationTokenExpires   = 7200
)

type Helper struct {
	redisClient *gredis.Redis
}

func NewHelper(host string, port, db int) *Helper {
	red := gredis.New(&gredis.Config{
		Host:      host,
		Port:      port,
		Db:        db,
		MaxActive: 100,
	})
	helper := &Helper{
		redisClient: red,
	}
	return helper
}

func (helper *Helper) GenerateToken(recordId string) ([]byte, error) {
	token, err := generator.GenRandomToken()
	if err != nil {
		return nil, err
	}

	key := DeviceTokenKeyPrefix + recordId

	_, err = helper.redisClient.Do("SET", key, token)
	if err != nil {
		return nil, err
	}
	_, err = helper.redisClient.Do("EXPIRE", key, DeviceTokenExpires)
	if err != nil {
		return nil, err
	}

	return token, nil

}

func (helper *Helper) ValidateToken(id string, token []byte) error {
	key := DeviceTokenKeyPrefix + id
	readToken, err := helper.redisClient.Do("GET", key)
	if err != nil {
		return err
	}

	if !reflect.DeepEqual(readToken, token) {
		return errors.New("token not match")
	}

	_, err = helper.redisClient.Do("EXPIRE", key, DeviceTokenExpires)
	if err != nil {
		return err
	}

	return nil
}

func (helper *Helper) ClearToken(id string) error {
	key := DeviceTokenKeyPrefix + id
	_, err := helper.redisClient.Do("DEL", key)
	if err != nil {
		return err
	}

	return nil
}

func (helper *Helper) GenerateAppToken(id string, key string) ([]byte, error) {
	token, err := generator.GenRandomToken()
	if err != nil {
		return nil, err
	}

	_, err = helper.redisClient.Do("SET", key, token)
	if err != nil {
		return nil, err
	}
	_, err = helper.redisClient.Do("EXPIRE", key, DeviceTokenExpires)
	if err != nil {
		return nil, err
	}

	return token, nil

}

func (helper *Helper) ValidateAppToken(key string, token []byte) error {
	readToken, err := helper.redisClient.Do("GET", key)
	if err != nil {
		return err
	}

	if !reflect.DeepEqual(readToken, token) {
		return errors.New("token not match.")
	}

	_, err = helper.redisClient.Do("EXPIRE", key, DeviceTokenExpires)
	if err != nil {
		return err
	}

	return nil
}
