package Nredis

import (
	"context"
	"fmt"
	rds "github.com/go-redis/redis/v8"
	"os"
	l4g "proxy/logger" //"github.com/sirupsen/logrus"
	"strconv"
	"strings"

	. "proxy/MsgDef"
)

var ctx = context.Background()

var rdb *rds.Client
var locRdb *rds.Client
func NewRedisClient(netType, addr, passwd string, sentinels []string) {
	if sentinels != nil {
		rdb = rds.NewFailoverClient(&rds.FailoverOptions{
			MasterName: "mymaster",
			SentinelAddrs: sentinels,
			Password: passwd,
			DB: 0,
			PoolSize: 5,
		})
		locRdb = rds.NewClient(&rds.Options{
			Network: netType,// The network type, either tcp or unix. Default is tcp.
			Addr:     addr,// can be: /var/run/redis/redis-server.sock???
			Password: passwd, // no password set
			DB:       0,  // use default DB
			PoolSize: 5,
		})
	} else {
		rdb = rds.NewClient(&rds.Options{
			Network: netType,// The network type, either tcp or unix. Default is tcp.
			Addr:     addr,// can be: /var/run/redis/redis-server.sock???
			Password: passwd, // no password set
			DB:       0,  // use default DB
			PoolSize: 5,
		})
		locRdb = rdb
	}

    pong, err := rdb.Ping(ctx).Result()
    if err != nil {
    	l4g.RedisLog.Errorf("%v, err: %v", pong, err)// Output: PONG <nil>
		os.Exit(1)
    } else {
    	l4g.RedisLog.Debugf("%v", pong)// Output: PONG <nil>
    }
    
    return
}

func CheckIfNeedToSyncDb() (bool, error) {
	/*if CheckIfRdbMaster() == false {
		return false, nil
	}*/

	size, err := rdb.DBSize(ctx).Result()
	if err == nil {
		if size < 10 {
			return true, nil
		} else {
			return false, nil
		}
	} else {
		return false, err
	}
}

func ClrTariffAndBundle() {
	rdb.FlushDB(ctx)
	/*n, err := rdb.Del(ctx, "Acct:*").Result()
	if err != nil {
		l4g.Errorf("Del Acct, err: %v", err)
	} else {
		l4g.Debugf("Del Acct, num[%d]", n)
	}
	
	n, err = rdb.Del(ctx, "Rr:*").Result()
	if err != nil {
		l4g.Errorf("Del Rr, err: %v", err)
	} else {
		l4g.Debugf("Del Rr, num[%d]", n)
	}
	
	n, err = rdb.Del(ctx, "Prefix:*").Result()
	if err != nil {
		l4g.Errorf("Del Prefix, err: %v", err)
	} else {
		l4g.Debugf("Del Prefix, num[%d]", n)
	}
	
	n, err = rdb.Del(ctx, "Tariff:*").Result()
	if err != nil {
		l4g.Errorf("Del Tariff, err: %v", err)
	} else {
		l4g.Debugf("Del Tariff, num[%d]", n)
	}*/
}

func CheckIfRdbMaster() bool {
	info := locRdb.Info(ctx, "Replication")
	if strings.Contains(info.Val(), "role:master") || strings.Contains(info.Val(), "role:active-replica") {
		return true
	} else {
		return false
	}
}

func SetRrId2RrKey(id int64, rrKey string) bool {
	err := rdb.Set(ctx, "RrId:"+strconv.FormatInt(id, 10), rrKey, 0).Err()
	if err != nil {
		l4g.RedisLog.Errorf("Set RrId:%d %s, err: %v", id, rrKey, err)
		return false
	} else {
		l4g.RedisLog.Infof("Set RrId:%d %s", id, rrKey)
		return true
	}
}

func GetRrKeyByRrId(id int64) string {
	var rrKey string
	var err error
	rrKey, err = rdb.Get(ctx, "RrId:"+strconv.FormatInt(id, 10)).Result()
	if err != nil {
		return ""
	} else {
		return rrKey
	}
}

func RdbSetRrRecord(rr *RrData) error {
	key := "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10)
	err := rdb.HMSet(ctx, key, "prdInstId", rr.PrdInstId, "serviceNbr", rr.ServiceNbr,
						"pricingSectionId", rr.PricingSectionId, "ofrInstId", rr.OfrInstId, "ofrId", rr.OfrId, 
						"ofrName", rr.OfrName, "beginTime", rr.BeginTime, "endTime", rr.EndTime, "freeValue", rr.FreeValue, "rateUnit", rr.RateUnit, "unitFee", rr.UnitFee,
						"usedValue", rr.UsedValue, "measureDomain", rr.MeasureDomain, "tariffId", rr.TariffId, "strategyId", rr.StrategyId, 
						"startRefTime", rr.StartRefTime, "endRefTime", rr.EndRefTime, "calcPriority", rr.CalcPriority, "eventPriority", rr.EventPriority).Err()
	if err != nil {
		l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
	} else {
		l4g.RedisLog.Debugf("HMSet Rr:%s, [%#v]", rr.ServiceNbr, rr)
		sadd := rdb.SAdd(ctx, "RrSet:"+rr.ServiceNbr+":"+rr.MeasureDomain, strconv.FormatInt(rr.RrId, 10))
		if sadd.Err() != nil {
			l4g.RedisLog.Errorf("SAdd RrSet:%s:%s %d, err: %v", rr.ServiceNbr, rr.MeasureDomain, rr.RrId, sadd.Err())
			return sadd.Err()
		} else {
			l4g.RedisLog.Debugf("SAdd RrSet:%s:%s %d", rr.ServiceNbr, rr.MeasureDomain, rr.RrId)
		}
		SetRrId2RrKey(rr.RrId, key)
	}
	
	return err
}

func RdbSetStrategyEventPriority(rr *RrData) error {
	err := rdb.HMSet(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10), "eventPriority", rr.EventPriority).Err()
	if err != nil {
		l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
	}

	return err
}

func RdbSetOfrCalcPriority(rr *RrData) error {
	err := rdb.HMSet(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10), "calcPriority", rr.CalcPriority).Err()
	if err != nil {
		l4g.RedisLog.Errorf("HMSet Rr:%s, err: %v", rr.ServiceNbr, err)
	}

	return err
}

// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbUpdateRrRecordOnly(rrId int64, ratableVal, usedVal int64, beginTime, endTime string) (int, error) {
	key := GetRrKeyByRrId(rrId)
	if key != "" {
		err := rdb.HMSet(ctx, key, "beginTime", beginTime, "endTime", endTime, "freeValue", ratableVal,
			"usedValue", usedVal).Err()
		if err != nil {
			l4g.RedisLog.Errorf("HMSet %s, err: %v", key, err)
			return -1, err
		} else {
			l4g.RedisLog.Debugf("HMSet %s, beginTime[%s], endTime[%s], free/used:[%d/%d]", key, beginTime, endTime, ratableVal, usedVal)
			return 1, nil
		}
	} else {
		l4g.RedisLog.Errorf("HMSet rrId[%d], err not found, beginTime[%s], endTime[%s], free/used:[%d/%d]", rrId, beginTime, endTime, ratableVal, usedVal)
		return 0, nil
	}
	/*var cursor uint64
	var err error
	for {
		var keys []string
		// 20 keys each scan
		keys, cursor, err = rdb.Scan(ctx, cursor, "Rr:*:"+strconv.FormatInt(rrId, 10), 2).Result()
		if err != nil {
			l4g.RedisLog.Errorf("Scan Rr:*:%d, err: %v", rrId, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			err := rdb.HMSet(ctx, key, "beginTime", beginTime, "endTime", endTime, "freeValue", ratableVal,
				"usedValue", usedVal).Err()
			if err != nil {
				l4g.RedisLog.Errorf("HMSet %s, err: %v", key, err)
			}
		}
		if cursor == 0 {
			break
		}
	}

	return err*/
}

// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbDelRrRecordByRrId(rrId int64) error {
	key := GetRrKeyByRrId(rrId)
	if key != "" {
		err := rdb.Del(ctx, key).Err()
		if err != nil {
			l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
		} else {
			l4g.RedisLog.Infof("Del %s succ", key)
			subFields := strings.Split(key, ":")
			if len(subFields) == 4 {
				_ = rdb.SRem(ctx, "RrSet:"+subFields[1]+":"+subFields[2], strconv.FormatInt(rrId, 10))
				l4g.RedisLog.Infof("SRem %d from RrSet:%s:%s", rrId, subFields[1], subFields[2])
				//return srem.Err()
			}

		}
		rdb.Del(ctx, "RrId:"+strconv.FormatInt(rrId, 10))
		l4g.RedisLog.Infof("Del RrId:%d", rrId)
		return nil
	}

	return nil
}

// "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.Itoa(rr.RrId)
func RdbDelRrRecordByServiceNbr(serviceNbr string) error {
	var cursor uint64
	var err error
	for {
		var keys []string
		// 20 keys each scan
		keys, cursor, err = rdb.Scan(ctx, cursor, "Rr:"+serviceNbr+":*", 30).Result()
		if err != nil {
			l4g.RedisLog.Errorf("Scan Rr:%s:*, err: %v", serviceNbr, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			err = rdb.Del(ctx, key).Err()
			if err != nil {
				l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
			} else {
				subFields := strings.Split(key, ":")
				if len(subFields) == 4 {
					_ = rdb.SRem(ctx, "RrSet:"+serviceNbr+":"+subFields[2], subFields[3])
					//return srem.Err()
				}
			}
		}
		if cursor == 0 {
			break
		}
	}

	return err
}

func RdbDelRrRecord(rr *RrData) error {
	err := rdb.Del(ctx, "Rr:"+rr.ServiceNbr+":"+rr.MeasureDomain+":"+strconv.FormatInt(rr.RrId, 10)).Err()
	if err != nil {
		l4g.RedisLog.Errorf("Del Rr:%s:%d, err: %v", rr.ServiceNbr, rr.RrId, err)
	} else {
		_ = rdb.SRem(ctx, "RrSet:"+rr.ServiceNbr+":"+rr.MeasureDomain, strconv.FormatInt(rr.RrId, 10))
	}
	
	return err
}

func RdbSetOfrRecord(ofrId int) error {
	err := rdb.Set(ctx, "Ofr:"+strconv.Itoa(ofrId), ofrId, 0).Err()
	if err != nil {
		l4g.RedisLog.Errorf("Set Ofr:%d, err: %v", ofrId, err)
	}
	
	return err
}

func RdbCheckIfOfrExist(ofrId int) bool {
	n, err := rdb.Exists(ctx, "Ofr:"+strconv.Itoa(ofrId)).Result()
	if err != nil {
		l4g.RedisLog.Errorf("Check Exists Ofr:%d, err: %v", ofrId, err)
		return false
	} else {
		if n >= 1 {
			return true
		} else {
			return false
		}
	}
}

func RdbSetPrefixRecord(prefix *PrefixData) error {
	sadd := rdb.SAdd(ctx, "Prefix:"+strconv.Itoa(prefix.StrategyId), prefix.AreaCode)
	return sadd.Err()
}

// Add holiday discount table
// Hd:tariff_id:tariff_seq:hdId, group, name, discount, state;;; type, subState, priority, begin, end;
// triggers: 1, create, modify(state), delete of tb_bil_holiday_rel;
//           2, modify(STATE), delete of tb_bil_holiday;
/* holiday discount
SELECT hd.HOLIDAY_GROUP, hd.HOLIDAY_PRIORITY, COUNT(1) AS HOLIDAY_COUNT FROM tb_bil_holiday hd
 WHERE (((hd.HOLIDAY_TYPE = '02' AND hd.HOLIDAY_BEGIN_DATE <= (WEEKDAY(SYSDATE()) + 1) AND hd.holiday_end_date >= (WEEKDAY(SYSDATE()) + 1))
     OR (hd.holiday_type = '03' AND DATE_FORMAT(SYSDATE(),'%m%d') >= DATE_FORMAT(CONCAT('2020', hd.HOLIDAY_BEGIN_DATE), '%m%d') AND DATE_FORMAT(SYSDATE(),'%m%d') <= DATE_FORMAT(CONCAT('2020', hd.holiday_end_date), '%m%d'))
     OR (hd.holiday_type = '04' AND DATE_FORMAT(SYSDATE(), '%H%i%s') >= DATE_FORMAT(STR_TO_DATE(CONCAT('20200101', hd.HOLIDAY_BEGIN_DATE), '%Y%m%d%H%i%s'),'%H%i%s')
     AND DATE_FORMAT(SYSDATE(), '%H%i%s') <= DATE_FORMAT(STR_TO_DATE(CONCAT('20200101', hd.holiday_end_date), '%Y%m%d%H%i%s'),'%H%i%s')))
		 and hd.STATE='L0R')
GROUP BY hd.HOLIDAY_PRIORITY, hd.HOLIDAY_GROUP;
*/
func RdbSetHolidayDiscountRecord(hd *HolidayDiscountData) error {
	err := rdb.HMSet(ctx, "Hd:"+strconv.Itoa(hd.TariffId)+":"+strconv.Itoa(hd.HdId),
		"ofrId", hd.OfrId, "tariffId", hd.TariffId, "tariffSeq", hd.TariffSeq, "hdGroup", hd.HdGroup,
		"hrState", hd.HrState, "hrDiscount", hd.HrDiscount, "hdId", hd.HdId, "hdName", hd.HdName,
		"hdType", hd.HdType, "hdState", hd.HdState, "hdPriority", hd.HdPriority,
		"hdBeginDate", hd.HdBeginDate, "hdEndDate", hd.HdEndDate).Err()
	if err != nil {
		l4g.RedisLog.Errorf("HMSet Hd:%d:%d, err: %v", hd.TariffId, hd.HdId, err)
	} else {
		sadd := rdb.SAdd(ctx, "HdSet:"+strconv.Itoa(hd.TariffId), strconv.Itoa(hd.HdId))
		if sadd.Err() != nil {
			l4g.RedisLog.Errorf("SAdd HdSet:%d %d, err: %v", hd.TariffId, hd.HdId, sadd.Err())
			return sadd.Err()
		}
		SetHdId2TariffId(hd.HdId, hd.TariffId)
	}

	return err
}

func RdbDelHolidayDiscountRecord(tariffId int) {
	var cursor uint64= 0
	for {
		// 20 keys each scan
		keys, cursorNew, err := rdb.SScan(ctx, "HdSet:"+strconv.Itoa(tariffId), cursor, "", 0).Result()
		if err != nil {
			l4g.RedisLog.Errorf("SScan HdSet:%d, err: %v", tariffId, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			hdKey := "Hd:"+strconv.Itoa(tariffId) + ":" + key
			err := rdb.Del(ctx, hdKey).Err()
			if err != nil {
				l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
			} else {
				//subFields := strings.Split(key, ":")
				//if len(subFields) == 3 && subFields[2] != "" {
					_ = rdb.SRem(ctx, "HdSet:"+strconv.Itoa(tariffId), key)
					//return srem.Err()
				//}
			}
		}
		if cursorNew == 0 {
			break
		} else {
			cursor = cursorNew
		}
	}
	_ = rdb.Del(ctx, "HdSet:"+strconv.Itoa(tariffId)).Err()

	return
}

func RdbDelHolidayDiscountRecordByHd(holidayId int) error {
	tariffIdStr := GetTariffIdByHdId(holidayId)
	tariffId, err := strconv.Atoi(tariffIdStr)
	if err != nil {
		l4g.RedisLog.Errorf("Get tariffId by HdId %d, err: %v", holidayId, err)
	} else {
		key := "Hd:" + strconv.Itoa(tariffId) + ":"+strconv.Itoa(holidayId)
		err := rdb.Del(ctx, key).Err()
		if err != nil {
			l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
		} else {
			_ = rdb.SRem(ctx, "HdSet:"+tariffIdStr, strconv.Itoa(holidayId))
		}
	}
	/*var cursor uint64
	for {
		var keys []string
		// 20 keys each scan
		keys, cursor, err = rdb.Scan(ctx, cursor, "Hd:*:"+strconv.Itoa(holidayId), 200).Result()
		if err != nil {
			l4g.RedisLog.Errorf("Scan Hd:*:%d, err: %v", holidayId, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			err := rdb.Del(ctx, key).Err()
			if err != nil {
				l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
			} else {
				subFields := strings.Split(key, ":")
				if len(subFields) == 3 && subFields[1] != "" {
					_ = rdb.SRem(ctx, "HdSet:"+subFields[1], strconv.Itoa(holidayId))
					//return srem.Err()
				}
			}
		}
		if cursor == 0 {
			break
		}
	}*/

	return err
}

// "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId)
func RdbDelTariffRecord(tariffId int) error {
	var cursor uint64
	var err error
	for {
		var keys []string
		// 20 keys each scan
		keys, cursor, err = rdb.Scan(ctx, cursor, "Tariff:*:"+strconv.Itoa(tariffId), 2).Result()
		if err != nil {
			l4g.RedisLog.Errorf("Scan Tariff:*:%d, err: %v", tariffId, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			err := rdb.Del(ctx, key).Err()
			if err != nil {
				l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
			} else {
				subFields := strings.Split(key, ":")
				if len(subFields) == 4 {
					_ = rdb.SRem(ctx, "TariffSet:"+subFields[1]+":"+subFields[2], strconv.Itoa(tariffId))
					//return srem.Err()
				}
			}
		}
		if cursor == 0 {
			break
		}
	}

	return err
}

// "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId)
func RdbDelTariffRecordByOfr(ofrId int) error {
	var cursor uint64
	var err error
	for {
		var keys []string
		// 20 keys each scan
		keys, cursor, err = rdb.Scan(ctx, cursor, "Tariff:"+strconv.Itoa(ofrId)+":*", 2).Result()
		if err != nil {
			l4g.RedisLog.Errorf("Scan Tariff:%d:*, err: %v", ofrId, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			err := rdb.Del(ctx, key).Err()
			if err != nil {
				l4g.RedisLog.Errorf("Del %s, err: %v", key, err)
			} else {
				subFields := strings.Split(key, ":")
				if len(subFields) == 4 {
					_ = rdb.SRem(ctx, "TariffSet:"+subFields[1]+":"+subFields[2], subFields[3])
					//return srem.Err()
				}
			}
		}
		if cursor == 0 {
			break
		}
	}

	return err
}

func RdbDelPrefixRecord(strategyId int, areaCode string) error {
	srem := rdb.SRem(ctx, "Prefix:"+strconv.Itoa(strategyId), areaCode)
	return srem.Err()
}

func RdbSetTariffRecord(tariff *TariffData) error {
	//&prd_inst_id, &service_nbr, &prd_inst_stas_id, &acct_id, &cust_id
	err := rdb.HMSet(ctx, "Tariff:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain+":"+strconv.Itoa(tariff.TariffId), "tariffId", tariff.TariffId,
						"tariffSeq", tariff.TariffSeq, "measureDomain", tariff.MeasureDomain,
						"startTime", tariff.StartTime, "endTime", tariff.EndTime, "feeUnit", tariff.FeeUnit, 
						"rateUnit", tariff.RateUnit, "calcPriority", tariff.CalcPriority, "eventPriority", tariff.EventPriority, "ofrId", tariff.OfrId, 
						"ofrName", tariff.OfrName, "strategyId", tariff.StrategyId, "strategyName", tariff.StrategyName).Err()
	if err != nil {
		l4g.RedisLog.Errorf("HMSet Tariff:%d, err: %v", tariff.TariffId, err)
	} else {
		sadd := rdb.SAdd(ctx, "TariffSet:"+strconv.Itoa(tariff.OfrId)+":"+tariff.MeasureDomain, strconv.Itoa(tariff.TariffId))
		if sadd.Err() != nil {
			l4g.RedisLog.Errorf("SAdd TariffSet:%d:%s %d, err: %v", tariff.OfrId, tariff.MeasureDomain, tariff.TariffId, sadd.Err())
			return sadd.Err()
		}
	}
	
	return err
}

func RdbGetRrByServiceNbrAndDomain(serviceNbrAndDomain string) (rsp string, err error) {
	var cursor uint64= 0
	for {
		keys, cursorNew, err := rdb.SScan(ctx, "RrSet:"+serviceNbrAndDomain, cursor, "", 0).Result()
		if err != nil {
			l4g.RedisLog.Errorf("SScan RrSet:%s, err: %v", serviceNbrAndDomain, err)
			break
		}

		//fmt.Printf("\nfound %d keys\n", len(keys))
		for _, key := range keys {
			rrKey := "Rr:"+serviceNbrAndDomain+":"+key
			res := rdb.HGetAll(ctx, rrKey)
			if res.Err() != nil {
				l4g.RedisLog.Errorf("HGetAll %s, err: %v", rrKey, err)
				return "err: HGetAll "+rrKey, err
			} else {
				var rrData RrData
				if err = res.Scan(&rrData); err != nil {
					l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", rrKey, err)
					return "err: Scan "+rrKey, err
				} else {
					l4g.RedisLog.Debugf("Get %s, [%v]", rrKey, rrData)
					rsp += fmt.Sprintf("%s:***************************************\r\nPrdInstId: %d\r\nOfrInstId: %d\r\nOfrId: %d\r\nOfrName: %s\r\nBeginTime: %s\r\nEndTime: %s\r\n",
						rrKey, rrData.PrdInstId, rrData.OfrInstId, rrData.OfrId, rrData.OfrName, rrData.BeginTime, rrData.EndTime)
					rsp += fmt.Sprintf("FreeValue: %d\r\nUsedValue: %d\r\nTariffId: %d\r\nStrategyId: %d\r\nCalcPriority: %d\r\nEventPriority: %d\r\nRateUnit: %d\r\nUnitFee: %d\r\n",
						rrData.FreeValue, rrData.UsedValue, rrData.TariffId, rrData.StrategyId, rrData.CalcPriority, rrData.EventPriority, rrData.RateUnit, rrData.UnitFee)
				}
			}
		}
		if cursorNew == 0 {
			break
		} else {
			cursor = cursorNew
		}
	}

	return rsp, err
}

func RdbGetTariffByOfrId(ofrId string) (*TariffData, error) {
	keys := rdb.Keys(ctx, "Tariff:"+ofrId+":*")
	err := keys.Err()
	if err != nil {
		l4g.RedisLog.Errorf("Get Keys of Tariff:%s:*, err: %v", ofrId, err)
		return nil, err
	} else {
		l4g.RedisLog.Debugf("Get Keys of Tariff:%s:*, keys:%v", ofrId, keys.Val())
	}

	// Scan the results into the struct.
	var ta TariffData
	for _, value := range keys.Val() {
		// Get the map. The same approach works for HmGet().
		res := rdb.HGetAll(ctx, value)
		err := res.Err()
		if err != nil {
			l4g.RedisLog.Errorf("HGetAll %s, err: %v", value, err)
			return nil, err
		}
		
		if err = res.Scan(&ta); err != nil {
			l4g.RedisLog.Errorf("HGetAll Scan %s, err: %v", value, err)
		} else {
			l4g.RedisLog.Debugf("Get %s, [%v]", value, ta)
			
			// Get prefix related tariff
			sMembers := rdb.SMembers(ctx, "Prefix:"+strconv.Itoa(ta.StrategyId))
			if sMembers.Err() == nil {
				l4g.RedisLog.Debugf("Prefix, [%v]", sMembers.Val())
			}
		}
	}
	
	return &ta, err
}
