package consume

import (
	"applet/app/cfg"
	"applet/app/db"
	"applet/app/e"
	utils2 "applet/app/utils"
	"applet/app/utils/cache"
	"applet/app/utils/logx"
	"applet/consume/md"
	"code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
	"code.fnuoos.com/EggPlanet/egg_models.git/src/model"
	"code.fnuoos.com/EggPlanet/egg_system_rules.git"
	"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
	md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
	"code.fnuoos.com/EggPlanet/egg_system_rules.git/svc"
	"code.fnuoos.com/EggPlanet/egg_system_rules.git/svc/sys_cfg"
	"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/streadway/amqp"
	"github.com/tidwall/gjson"
	"time"
)

func VideoRewardConsume(queue md.MqQueue) {
	fmt.Println(">>>>>>>>>>>>VideoRewardConsume>>>>>>>>>>>>")
	ch, err := rabbit.Cfg.Pool.GetChannel()
	if err != nil {
		logx.Error(err)
		return
	}
	defer ch.Release()
	//1、将自己绑定到交换机上
	ch.Bind(queue.Name, queue.ExchangeName, queue.RoutKey)
	//2、取出数据进行消费
	ch.Qos(100)
	delivery := ch.Consume(queue.Name, false)

	egg_system_rules.Init(cfg.RedisAddr)
	var res amqp.Delivery
	var ok bool
	for {
		res, ok = <-delivery
		if ok == true {
			err = handleVideoRewardConsume(ch, res.Body)
			if err != nil {
				fmt.Println("VideoRewardConsume_ERR:::::", err.Error())
				utils2.FilePutContents("VideoRewardConsume_ERR", utils2.SerializeStr(map[string]interface{}{
					"body": res.Body,
					"err":  err.Error(),
				}))
				_ = res.Reject(false)
				//TODO::重新推回队列末尾,避免造成队列堵塞
				var msg *md.VideoReward
				json.Unmarshal(res.Body, &msg)
				ch.Publish(queue.ExchangeName, msg, queue.RoutKey)
			} else {
				//_ = res.Reject(false)
				err = res.Ack(true)
			}

			fmt.Println("err ::: ", err)
		} else {
			panic(errors.New("error getting message"))
		}
	}
	fmt.Println("get msg done")
}

func handleVideoRewardConsume(ch *rabbit.Channel, msgData []byte) error {
	time.Sleep(time.Duration(100) * time.Millisecond) //休眠100毫秒
	// 1.解析mq中queue的数据结构体
	var msg *md.VideoReward
	err := json.Unmarshal(msgData, &msg)
	if err != nil {
		return err
	}
	//1、分布式锁阻拦
	requestIdPrefix := fmt.Sprintf("video.reward.lock:%s", msg.Uid)
	cb, err := svc.HandleDistributedLockForComm(msg.Uid, "video.reward.lock.update:%s", requestIdPrefix)
	if err != nil {
		return err
	}
	if cb != nil {
		defer cb() // 释放锁
	}
	eg := db.Db
	sysCfgDb := sys_cfg.NewSysCfgDb(db.Db)
	videoBase := sysCfgDb.SysCfgGetWithDb("video_base")
	sess := eg.NewSession()
	defer sess.Close()
	sess.Begin()
	NewVideoTotalDb := implement.NewVideoTotalDb(db.Db)
	total, _ := NewVideoTotalDb.GetVideoTotalSess(sess, msg.Uid, time.Now().Format("20060102"))
	if total == nil {
		total = &model.VideoTotal{
			Uid:  utils2.StrToInt(msg.Uid),
			Date: utils2.StrToInt(time.Now().Format("20060102")),
			Time: time.Now(),
		}
		insert, err := sess.Insert(total)
		if insert == 0 || err != nil {
			sess.Rollback()
			return e.NewErr(400, "获取奖励失败")
		}
	}
	Leave := utils2.StrToInt(gjson.Get(videoBase, "total").String()) - total.Total
	if Leave-1 < 0 {
		return nil
	}
	total.Total++
	update, err2 := sess.Where("id=?", total.Id).Cols("total").Update(total)
	if update == 0 || err2 != nil {
		sess.Rollback()
		return e.NewErr(400, "获取奖励失败")
	}
	sess.Commit()
	numKey := "video.num:" + time.Now().Format("20060102") + "." + msg.Uid
	todayRange := utils2.GetTimeRange("today")
	cache.SetEx(numKey, utils2.IntToStr(total.Total), int(todayRange["end"]-time.Now().Unix()))
	NewEggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(db.Db)
	eggData, _ := NewEggEnergyBasicSettingDb.EggEnergyBasicSettingGetOne()
	err = ch.PublishV2(md2.EggEnergyExchange, md2.EggEnergyStructForDealUserVirtualCoinData{
		Kind:         "add",
		Title:        enum.EggEnergyVideoRewardPersonalActiveCoin.String(),
		TransferType: int(enum.EggEnergyVideoRewardPersonalActiveCoin),
		CoinId:       eggData.PersonEggPointsCoinId,
		Uid:          utils2.StrToInt64(msg.Uid),
		Amount:       utils2.StrToFloat64(gjson.Get(videoBase, "reward").String()),
	}, md2.EggEnergyRoutKeyForDealUserVirtualCoinData)
	if err != nil {
		ch.PublishV2(md2.EggEnergyExchange, md2.EggEnergyStructForDealUserVirtualCoinData{
			Kind:         "add",
			Title:        enum.EggEnergyVideoRewardPersonalActiveCoin.String(),
			TransferType: int(enum.EggEnergyVideoRewardPersonalActiveCoin),
			CoinId:       eggData.PersonEggPointsCoinId,
			Uid:          utils2.StrToInt64(msg.Uid),
			Amount:       utils2.StrToFloat64(gjson.Get(videoBase, "reward").String()),
		}, md2.EggEnergyRoutKeyForDealUserVirtualCoinData)
	}
	return nil
}