package main

import (
	"../log"
	"../mod"
	"../nt"
	pbs "../protos"
	"../utils"
	"./pb"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"go.uber.org/zap"
	"math"
	"net/http"
	"strconv"
	"time"
)

//入口
func Router(c *gin.Context) {
	var req dbdzRequest
	if err := decrypt(c, &req); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"status":   pb.Ec_FAILED,
			"balance":  0,
			"err_text": "king err",
		})
		return
	}

	switch req.Action {

	case CANCEL_ACTION:
		Inform(&req, c)
	case GET_BALANCE:
		GetBalance(&req, c)
	case BET_GAME_INFO:
		Transfer(&req, c)

	}
}

//  获取会员余额
func GetBalance(req *dbdzRequest, c *gin.Context) {

	errText := ""
	ec := pb.Ec_SUCCEED
	var balancef float64 = 0.00

	defer func() {
		log.Info("wallet GetBalance", zap.String("guid", req.Uid), zap.Float64("balance", balancef), zap.Any("status", ec),
			zap.String("errText", errText))
		if ec == pb.Ec_SUCCEED {
			c.JSON(http.StatusOK, gin.H{
				"status":  "0000",
				"balance": balancef,
			})
		} else {
			c.JSON(http.StatusOK, gin.H{
				"status":   fmt.Sprintf("%s", ec),
				"err_text": errText,
			})
		}

	}()

	guid, err := strconv.ParseUint(req.Uid, 10, 64)
	if err != nil {
		ec = pb.Ec_FAILED
		errText = "king err"
		return
	}
	// 取得余额
	sbalance, err := mod.GetUserAttr(guid, "balance")
	if nil != err {
		ec = pb.Ec_IU
		errText = "MEMBER_NOT_FOUND"
		return
	}

	balancef, err = strconv.ParseFloat(sbalance, 10)
	if nil != err {
		ec = pb.Ec_FAILED
		errText = "king err"
		return
	}
	balancef = ConvertBalance(balancef)
}

// 下注及游戏结果
func Transfer(req *dbdzRequest, c *gin.Context) {

	var bbalance float64 = 0.00 //转帐前余额
	errText := "king err"
	ec := pb.Ec_SUCCEED

	defer func() {
		jb := gin.H{
			"status":  "0000",
			"balance": bbalance,
		}

		if ec == pb.Ec_SUCCEED {
			log.Info("Transfer success", zap.Any("data", jb))
			c.JSON(http.StatusOK, jb)
			//异步往redis里放入夺宝电子每局结算
			tm, _ := time.ParseInLocation("02-01-2006 15:04:05", req.GameDate, time.Local)
			gameTime := tm.Unix() + 12*60*60
			gameId, gameMaker, existed := findGameIdBygTypemType(strconv.Itoa(req.GType), strconv.Itoa(req.MType))
			bbalance := BalanceToPlatform(bbalance)
			bet := math.Abs(BalanceToPlatform(req.Bet))
			netWin := BalanceToPlatform(req.NetWin)

			if !existed {
				log.Error("Transfer findGameIdBygTypemType null", zap.String("guid", req.Uid),
					zap.Int("gType", req.GType), zap.Int("mType", req.MType))
				return
			}
			dbdz_res := NatsOrders{bbalance, 0, netWin, gameMaker, gameId,
				strconv.FormatInt(req.GameSeqNo, 10), bet, gameTime, gameTime}
			go func() {
				dBDZ_Nats(req.Uid, &dbdz_res)
			}()
			return
		} else {
			faild := utils.H{
				"status":   fmt.Sprintf("%s", ec),
				"err_text": errText,
			}
			log.Info("Transfer faild", zap.Any("data", faild))
			c.JSON(http.StatusOK, faild)
		}

		if ec != pb.Ec_SUCCEED && ec != pb.Ec_DTS { //只保留非流水号重复的情况
			// 保存失败订单
			log.Info("Transfer failed", zap.Any("status", ec))
			bytes, err := json.Marshal(utils.H{
				"status":   fmt.Sprintf("%s", ec),
				"err_text": errText,
			})

			if err == nil {
				log.Debug("Transfer save fild order", zap.Any("res", fmt.Sprintf("%s", bytes)), zap.Any("data", req))
				err = mod.UpdateDbdzTradeFailed(AgentName, strconv.FormatInt(req.TransferId, 10), fmt.Sprintf("%s", bytes))
				if nil != err {
					log.Error("UpdateDbdzTradeFailed", zap.Any("data", req))
				}
			} else {
				log.Error("Marshal", zap.Any("data", req))
			}

		}
	}()

	guid_, err := strconv.ParseUint(req.Uid, 10, 64) //玩家是否存在
	if err != nil {
		ec = pb.Ec_FAILED
		return
	}
	guid, err := mod.GetUserAttr(guid_, "account")
	if nil != err {
		ec = pb.Ec_UICBF
		return
	}
	if guid == "" {
		ec = pb.Ec_UICBF
		return
	}

	// 检查该笔交易是否已成功
	val, err := mod.GetDBDZTransferId(AgentName, strconv.FormatInt(req.TransferId, 10))
	if (nil != err && err != redis.Nil) || len(val) > 0 {
		ec = pb.Ec_DTS
		return
	}

	// 取得余额
	sbalance, err := mod.GetUserAttr(guid_, "balance")
	if nil != err {
		ec = pb.Ec_FAILED
		return
	}
	bbalance, err = strconv.ParseFloat(sbalance, 10)
	if nil != err {
		ec = pb.Ec_FAILED
		return
	}

	if bbalance == 0.00 { //玩家余额为0
		ec = pb.Ec_UBIZ
		return
	}

	bbalance = ConvertBalance(bbalance)
	// 扣款
	var delta int64 = 0
	delta = ConvertAmount(req.NetWin)

	if bbalance+req.NetWin < 0 { //玩家余额不足
		ec = pb.Ec_YCBNE
		return
	}

	bbalance = bbalance + req.NetWin
	str := fmt.Sprintf("%.2f", bbalance)
	bbalance, _ = strconv.ParseFloat(str, 64)

	save_req := utils.H{
		"ts":             req.Ts,
		"gameSeqNo":      req.GameSeqNo,
		"uid":            req.Uid,
		"gType":          req.GType,
		"mType":          req.MType,
		"reportdDate":    req.ReportDate,
		"gameDate":       req.GameDate,
		"currency":       req.Currency,
		"bet":            req.Bet,
		"win":            req.Win,
		"netWin":         req.NetWin,
		"denom":          req.Denom,
		"ipAddress":      req.IpAddress,
		"clientType":     req.ClientType,
		"systemTakeWin":  req.SystemTakeWin,
		"lastModifyTime": req.LastModifyTime,
	}

	switch req.GType {
	case 0:
		save_req["jackpotWin"] = req.JackpotWin
		save_req["jackpotContribute"] = req.JackpotContribute
		save_req["hasFreegame"] = req.HasFreegame
		save_req["hasGamble"] = req.HasGamble
	case 7:
		save_req["roomType"] = req.RoomType
	case 9:
		save_req["hasGamble"] = req.HasGamble
		save_req["hasBonusGame"] = req.HasBonusGame
	case 12:
		save_req["hasBonusGame"] = req.HasBonusGame
	}

	bytes, err := json.Marshal(save_req)
	if err != nil {
		ec = pb.Ec_FAILED
		return
	}

	arr, err := UpdateTransferStatus(guid_, delta, strconv.FormatInt(req.TransferId, 10), bytes)
	if nil != err {
		ec = pb.Ec_FAILED
		return
	}
	newBalance := utils.If_to_int64(arr[0], 0)
	// 异步执行
	go func() {
		// Rpc
		err = RpcNotifyBalanceChange(guid_, delta, newBalance)
	}()

}

// 取消下注
func Inform(req *dbdzRequest, c *gin.Context) {

	var newBalancef int64 = 0
	var err_text = "king err"
	ec := pb.Ec_SUCCEED

	defer func() {
		if ec == pb.Ec_SUCCEED {
			c.JSON(http.StatusOK, gin.H{
				"status":  "0000",
				"balance": newBalancef,
			})
			log.Debug("Inform success")
		} else {
			log.Debug("Inform failed", zap.String("data", fmt.Sprintf("%s", ec)))
			c.JSON(http.StatusOK, gin.H{
				"status":   fmt.Sprintf("%s", ec),
				"err_text": err_text,
			})

		}
	}()

	guid, err := strconv.ParseUint(req.Uid, 10, 64)
	if err != nil {
		log.Debug("Inform ParseUint", zap.Error(err))
		ec = pb.Ec_FAILED
		return
	}
	//  guid 是否存在
	account, err := mod.GetUserAttr(guid, "account")
	if err != nil {
		log.Debug("Inform GetUserAttr err", zap.Error(err))
		ec = pb.Ec_FAILED
		return
	}
	if account == "" {
		log.Debug("Inform GetUserAttr null")
		ec = pb.Ec_IU
		return
	}

	// 取得余额
	sbalance, err := mod.GetUserAttr(guid, "balance")
	if nil != err {
		log.Debug("Inform GetUserAttr sbalance err", zap.Error(err))
		ec = pb.Ec_FAILED
		return
	}

	newBalancef, err = strconv.ParseInt(sbalance, 10, 64)
	if err != nil {
		log.Debug("Inform ParseInt sbalance err", zap.Error(err))
		ec = pb.Ec_FAILED
		return
	}

	if err := mod.RemDBDZTradeFailed(AgentName, strconv.FormatInt(req.TransferId, 10)); err != nil {
		log.Debug("Inform RemDBDZTradeFailed err", zap.Error(err))
		ec = pb.Ec_FAILED
		log.Error("Unmarshal err", zap.Any("data", req))
	}

}

//每局结算往nats里发
func dBDZ_Nats(guid string, res *NatsOrders) {

	log.Debug("dBDZ_Nats", zap.String("guid", guid), zap.Float64("balance", res.balance),
		zap.Float64("tax", res.tax), zap.Float64("winlose", res.winLose), zap.Int64("gameMaker", res.gameMaker),
		zap.Int64("gameId", res.game_id), zap.String("bet_id", res.bet_id), zap.Float64("bet", res.bet),
		zap.Int64("start_time", res.start_time), zap.Int64("end_time", res.end_time))

	guid_, err := strconv.ParseUint(guid, 10, 64)
	if nil != err {
		log.Error("dBDZ_Nats ParseUint err", zap.Error(err), zap.String("guid", guid), zap.Any("natsOrder", *res))
		return
	}

	nt.WriteUserMsg(guid_, int32(pbs.Event_JDB_SETTLEMENT), "dbdz", utils.H{
		"balance":    res.balance,
		"tax":        res.tax,
		"winLose":    res.winLose,
		"game_id":    res.game_id,
		"channel_id": res.gameMaker, //接入游戏厂商 4001
		"bet_id":     res.bet_id,
		"bet":        res.bet,
		"start_time": res.start_time,
		"end_time":   res.end_time,
	})

	log.Debug("dBDZ_Nats success", zap.String("guid", guid))
}
