package redis

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

	//"strconv"
	//. "../MsgDef"
)

var ctx = context.Background()

var rdb *rds.Client
func NewRedisClient(netType, addr string) {
	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: "", // no password set
		DB:       0,  // use default DB
		PoolSize: 5,
	})

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

	return
}

type PcfUsrData struct {
	Msisdn string `redis:"msisdn"`
	PccRules string `redis:"pcc_rules"`
}

func MmlAddPcfUser(params []string) (rsp string) {
	var imsi, msisdn, pccRules string

	for _, val := range params {
		if strings.HasPrefix(val, "imsi=") {
			imsi = val[len("imsi="):]
		} else if strings.HasPrefix(val, "msisdn=") {
			msisdn = val[len("msisdn="):]
		} else if strings.HasPrefix(val, "pcc_rules=") {
			pccRules = val[len("pcc_rules="):]
		}
	}

	err := rdb.HMSet(ctx, "pcfUser:"+imsi, "msisdn", msisdn, "pcc_rules", pccRules).Err()
	if err != nil {
		rsp = fmt.Sprintf("HMSet pcfUser:%s, err: %v", imsi, err)
	}

	return rsp
}

func MmlModPcfUser(params []string) (rsp string) {
	var imsi, msisdn, pccRules string

	for _, val := range params {
		if strings.HasPrefix(val, "imsi=") {
			imsi = val[len("imsi="):]
		} else if strings.HasPrefix(val, "msisdn=") {
			msisdn = val[len("msisdn="):]
		} else if strings.HasPrefix(val, "pcc_rules=") {
			pccRules = val[len("pcc_rules="):]
		}
	}

	err := rdb.HMSet(ctx, "pcfUser:"+imsi, "msisdn", msisdn, "pcc_rules", pccRules).Err()
	if err != nil {
		rsp = fmt.Sprintf("HMSet pcfUser:%s, err: %v", imsi, err)
	}

	return rsp
}

func MmlDelPcfUser(params []string) (rsp string) {
	var imsi string
	for _, val := range params {
		if strings.HasPrefix(val, "imsi=") {
			imsi = val[len("imsi="):]
		}
	}

	err := rdb.Del(ctx, "pcfUser:"+imsi).Err()
	if err != nil {
		rsp = fmt.Sprintf("Del pcfUser:%s, err: %v", imsi, err)
	}

	return rsp
}

func MmlDspPcfUser(params []string) (rsp string) {
	var imsi string

	for _, val := range params {
		if strings.HasPrefix(val, "imsi=") {
			imsi = val[len("imsi="):]
		}
	}

	res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
	err := res.Err()
	if err != nil {
		rsp = fmt.Sprintf("HGetAll pcfUser:%s, err: %v", imsi, err)
		return rsp
	}

	// Scan the results into the struct.
	var usrData PcfUsrData
	if err = res.Scan(&usrData); err != nil {
		rsp = fmt.Sprintf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
	} else {
		rsp = fmt.Sprintf("pcfUser:imsi=%s, [%v]", imsi, usrData)
	}

	return rsp
}

func GetPcfUsrDataByImsi(imsi string) (usrData PcfUsrData, err error) {
	res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
	err = res.Err()
	if err != nil {
		l4g.RedisLog.Errorf("HGetAll pcfUser:%s, err: %v", imsi, err)
		return
	}

	// Scan the results into the struct.
	if err = res.Scan(&usrData); err != nil {
		l4g.RedisLog.Errorf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
		return
	} else {
		return
	}
}

func GetPcfUsrPccRulesByImsi(imsi string) (pccRules string, err error) {
	res := rdb.HGetAll(ctx, "pcfUser:"+imsi)
	err = res.Err()
	if err != nil {
		l4g.RedisLog.Errorf("HGetAll pcfUser:%s, err: %v", imsi, err)
		return "", err
	}

	// Scan the results into the struct.
	var usrData PcfUsrData
	if err = res.Scan(&usrData); err != nil {
		l4g.RedisLog.Errorf("HGetAll Scan pcfUser:%s, err: %v", imsi, err)
		return "", err
	} else {
		return usrData.PccRules, nil
	}
}

func MmlBadPcfUser(params []string) (rsp string) {
	var pccRules string
	var startImsi, startMsisdn int64
	var subNum int64= 0

	for _, val := range params {
		if strings.HasPrefix(val, "start_imsi=") {
			startImsi, _ = strconv.ParseInt(val[len("start_imsi="):], 10, 64)
		} else if strings.HasPrefix(val, "start_msisdn=") {
			startMsisdn, _ = strconv.ParseInt(val[len("start_msisdn="):], 10, 64)
		} else if strings.HasPrefix(val, "pcc_rules=") {
			pccRules = val[len("pcc_rules="):]
		} else if strings.HasPrefix(val, "sub_num=") {
			subNum, _ = strconv.ParseInt(val[len("sub_num="):], 10, 64)
		}
	}

	var i int64= 0
	for i=0; i<subNum; i++ {
		var imsi, msisdn string
		imsi = fmt.Sprintf("imsi=%d", startImsi+i)
		msisdn = fmt.Sprintf("msisdn=%d", startMsisdn+i)
		mmlParams := []string{imsi, msisdn, pccRules}
		MmlAddPcfUser(mmlParams)
	}

	rsp = "Command OK"
	return
}

func MmlBdePcfUser(params []string) (rsp string) {
	var startImsi int64= 0
	var subNum int64= 0

	for _, val := range params {
		if strings.HasPrefix(val, "imsi=") {
			startImsi, _ = strconv.ParseInt(val[len("start_imsi="):], 10, 64)
		} else if strings.HasPrefix(val, "sub_num=") {
			subNum, _ = strconv.ParseInt(val[len("sub_num="):], 10, 64)
		}
	}

	var i int64= 0
	for i=0; i<subNum; i++ {
		var imsi string
		imsi = fmt.Sprintf("imsi=%d", startImsi+i)
		mmlParams := []string{imsi}
		MmlDelPcfUser(mmlParams)
	}

	rsp = "Command OK"
	return
}

func HandleMmlCmdRequest(cmd []string) string {
	paramStr := strings.TrimPrefix(cmd[1], "pcfuser:")
	params := strings.Split(paramStr, ",")

	switch cmd[0] {
	case "add":
		return MmlAddPcfUser(params)
	case "mod":
		return MmlModPcfUser(params)
	case "del":
		return MmlDelPcfUser(params)
	case "dsp":
		return MmlDspPcfUser(params)
	case "bad":
		return MmlBadPcfUser(params)
	case "bde":
		return MmlBdePcfUser(params)
	default:
		return "Unkown MML CMD"
	}
}

