package cron

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"go.uber.org/zap"
	"courseSign/server/global"
	"courseSign/server/model/twi"
	"courseSign/server/model/user"
)

type TreeJob struct {
	JobName string
	UsersIdMap map[int64]*twi.TwiMetamask
}

var isTreeJobRun bool

// Run
// 用户关系生成脚本
// 1、从用户表种获取还没有生成关系的用户列表
// 2、生成对应的关系路径以及上级 顶层
// 3、批量插入用户关系表中
func (job TreeJob) Run() {
	job.JobName = "TreeJob"
	if isTreeJobRun {
		global.GVA_LOG.Info(job.JobName, zap.String("job", "already run"))
		return
	}
	isTreeJobRun = true
	global.GVA_LOG.Info(job.JobName, zap.String("job", "start"))
	t := time.Now()
	defer func() {
		isTreeJobRun = false
		global.GVA_LOG.Info("TreeJob 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)

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

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

	return
}

func (job *TreeJob) GetUsersAll() 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
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("total invitor count",len(list)))
	return err
}

// UpdateUserTree 更新关系树
func (job *TreeJob) UpdateUserTree() error {
	list := make([]*twi.TwiMetamask,0)
	err := global.GVA_DB.Raw("SELECT a.* from twi_metamask as a left join users_tree as u on a.id = u.user_id where u.user_id is null").Scan(&list).Error
	if err != nil {
		global.GVA_LOG.Error(job.JobName, zap.String("query users err", err.Error()))
		return err
	}
	global.GVA_LOG.Info(job.JobName,zap.Any("未更新关系地址数",len(list)))
	data := make([]*user.UsersTree,0)
	for _, v := range list {
		ut := &user.UsersTree{}
		invitation,err := job.buildUserInvitation(int64(v.ID))
		if err != nil {
			global.GVA_LOG.Error(job.JobName, zap.String("buildUserInvitation err", err.Error()))
			return err
		}
		ids := strings.Split(invitation,",")
		top,_:= strconv.Atoi(ids[0])
		*ut.TopId = top
		*ut.InviterId = int(v.InvitorId)
		ut.Path = invitation
		data = append(data,ut)
	}
	for _, v:= range data {
		err = global.GVA_DB.Save(v).Error
		if err != nil {
			global.GVA_LOG.Error(job.JobName, zap.String("save UserInvitation err", err.Error()))
			return err
		}
	}

	return nil
}

// 构建用户路径
func (job *TreeJob) buildUserInvitation(uid int64) (string,error) {
	if uid == 0 {
		return "",errors.New("empty uid")
	}
	if _,ok := job.UsersIdMap[uid];ok {
		if job.UsersIdMap[uid].Invitor == "" {
			return "",errors.New("no invitor")
		} else {
			invitation,err := job.buildUserInvitation(job.UsersIdMap[uid].InvitorId)
			if err != nil {
				return "",err
			}
			return fmt.Sprintf("%s,%d",invitation,uid),nil
		}
	} else {
		return "",errors.New("uid not exists")
	}
}