package cron

import (
	"time"

	"go.uber.org/zap"
	"gorm.io/gorm"
	"courseSign/server/global"
	"courseSign/server/model/airDrop"
	"courseSign/server/model/entrustPool"
	"courseSign/server/model/twi"
)

type RewardJob struct {
	JobName string
	UsersIdMap map[int64]*twi.TwiMetamask
	UsersAddrMap map[string]*twi.TwiMetamask
	Pools map[string]*entrustPool.Pool
}

var isRewardJobRun bool
const RewardTime = 1727712000 // 2024-10-1

// Run 发送投票奖励
// 1、解析pool_addr_txs 交易 符合条件的出矿数据 给推广者相应奖励
// 2、然后将相应数据写入 pool_reward_list
func (job RewardJob) Run() {
	job.JobName = "RewardJob"
	if isRewardJobRun {
		global.GVA_LOG.Info(job.JobName, zap.String("job", "already run"))
		return
	}
	isRewardJobRun = true
	global.GVA_LOG.Info(job.JobName, zap.String("job", "start"))
	t := time.Now()
	defer func() {
		isRewardJobRun = false
		global.GVA_LOG.Info("RewardJob done")
		global.GVA_LOG.Info(job.JobName, zap.String("cost", time.Since(t).String()))
	}()
	var err error
	job.UsersIdMap = make(map[int64]*twi.TwiMetamask,0)
	job.UsersAddrMap = make(map[string]*twi.TwiMetamask,0)
	job.Pools = make(map[string]*entrustPool.Pool,0)

	err = job.SetVars()
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("UpdateUserInvitor err", err.Error()))
		return
	}

	err = job.UpdateUserReward()
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("UpdateUserTree err", err.Error()))
		return
	}

	return
}

func (job *RewardJob) SetVars() error {
	list := make([]*twi.TwiMetamask,0)
	err := global.GVA_DB.Model(&twi.TwiMetamask{}).Where("invitor != null ").Find(&list).Error
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("UpdateUserTree err", err.Error()))
		return err
	}
	for _, v := range list {
		job.UsersIdMap[int64(v.ID)] = v
		job.UsersAddrMap[v.Address] = v
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("total invitor count",len(list)))

	pools := make([]*entrustPool.Pool,0)
	err = global.GVA_DB.Model(&entrustPool.Pool{}).Find(&pools).Error
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("query pool err", err.Error()))
		return err
	}
	for _,v := range pools {
		job.Pools[v.MinerAddr] = v
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("total pools count",len(pools)))
	return err
}

// UpdateUserReward 更新用户推广奖励
func (job *RewardJob) UpdateUserReward() error {
	var nt = time.Now()
	var lastId int64
	var last entrustPool.PoolRewardList
	err := global.GVA_DB.Model(&entrustPool.PoolRewardList{}).Order("id desc").First(&last).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		global.GVA_LOG.Error(job.JobName, zap.String("query last record err", err.Error()))
		return err
	}
	if lastId == 0 {
		lastId = 650000
	}
	list := make([]*entrustPool.PoolAddrTxs,0)
	err = global.GVA_DB.Model(&entrustPool.PoolAddrTxs{}).Where("id > ?",lastId).Limit(100).Find(&list).Error
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("query PoolAddrTxs err", err.Error()))
		return err
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("待计算交易数量",len(list)))
	var updateId int64
	data := make([]entrustPool.PoolRewardList,0)
	for _, v := range list {
		if int64(v.ID) > updateId {
			updateId = int64(v.ID)
		}
		// 只结算后台的矿池 和 用户地址
		if _,ok := job.Pools[v.MinerAddr];ok {
			if u,ok2 := job.UsersAddrMap[v.ReturnAddr];ok2 {
				// 新用户100天  绑定twitter和telegram的 加100天
				// 当前计算的是昨天的数据
				if u.InvitorId > 0 {
					// 绑定用户 200天
					if nt.Unix() - u.CreatedAt.Unix() - 1 < 200 {
						reward := entrustPool.PoolRewardList{}
						*reward.RewardId = int(v.ID)
						*reward.Amount = float64(1)
						reward.CreatedAt = nt
						*reward.UserId = int(u.ID)
						*reward.InvitorId = int(u.InvitorId)
						*reward.Status = airDrop.TxCommon
						data = append(data,reward)
					}
				} else {
					// 新用户100天
					if nt.Unix() - u.CreatedAt.Unix() - 1 < 100 {
						reward := entrustPool.PoolRewardList{}
						*reward.RewardId = int(v.ID)
						*reward.Amount = float64(1)
						reward.CreatedAt = nt
						*reward.UserId = int(u.ID)
						*reward.Status = airDrop.TxCommon
						data = append(data,reward)
					}
				}

			}
		}
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("待更新投票奖励数量",len(list)))
	for _, v := range data {
		err = global.GVA_DB.Save(v).Error
		if err != nil {
			global.GVA_LOG.Error(job.JobName, zap.String("save pool reward list err", err.Error()))
			return err
		}
	}

	return nil
}
