package cache

import (
	"errors"
	"fmt"
	"git.noahlan.cn/n-admin/n-admin-server/dal"
	"git.noahlan.cn/noahlan/ntool/nlog"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"time"
)

type (
	CodeCache interface {
		// GetCachedCode 获取缓存的Code和ttl
		// subject: 主体
		// source: 来源
		// typ: 类型
		GetCachedCode(subject, source, typ string) (string, int, error)
		// CacheCode 缓存Code
		CacheCode(code, subject, source, typ string, expiresIn int) error
		// DelCode 移除subject与用途对应的code
		DelCode(subject, source, typ string) error
	}
	codeCacheMgr struct {
		cache cache.Cache
		redis *redis.Redis
	}
)

func NewCodeCacheMgr(cache cache.Cache, rds *redis.Redis) CodeCache {
	return &codeCacheMgr{cache: cache, redis: rds}
}

func (m *codeCacheMgr) GetCachedCode(subject, source, typ string) (string, int, error) {
	var code string
	key := fmt.Sprintf("%s_CODE:%s:%s", source, typ, subject)
	err := m.cache.Get(key, &code)
	if err != nil && !errors.Is(err, dal.ErrCacheNotFound) {
		nlog.Errorw("[CodeCache] get code err", nlog.Field("err", err.Error()))
		return "", 0, err
	}
	ttl, _ := m.redis.Ttl(key)
	return code, ttl, nil
}

func (m *codeCacheMgr) CacheCode(code, subject, usage, typ string, expiresIn int) error {
	key := fmt.Sprintf("%s_CODE:%s:%s", usage, typ, subject)
	err := m.cache.SetWithExpire(key, code, time.Second*time.Duration(expiresIn))
	if err != nil {
		nlog.Errorw("[CodeCache] caching err", nlog.Field("err", err.Error()))
		return err
	}
	return nil
}

func (m *codeCacheMgr) DelCode(subject, usage, typ string) error {
	key := fmt.Sprintf("%s_CODE:%s:%s", usage, typ, subject)
	err := m.cache.Del(key)
	if err != nil {
		nlog.Errorw("[CodeCache] delete key err", nlog.Field("err", err.Error()))
		return err
	}
	return nil
}
