package services

import (
	"eta/eta_api/models"
	"eta/eta_api/models/report_approve"
	"eta/eta_api/models/smart_report"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/utils"
	"fmt"
	"sort"
	"time"
)

// GetReportClassifyTreeRecursive 递归获取报告分类树
func GetReportClassifyTreeRecursive(list []*models.Classify, parentId int) []*report_approve.ReportClassifyTreeItem {
	res := make([]*report_approve.ReportClassifyTreeItem, 0)
	for _, v := range list {
		if v.ParentId == parentId {
			t := new(report_approve.ReportClassifyTreeItem)
			t.ClassifyId = v.Id
			t.ClassifyName = v.ClassifyName
			t.ParentId = v.ParentId
			t.Children = GetReportClassifyTreeRecursive(list, v.Id)
			res = append(res, t)
		}
	}
	return res
}

// CheckReportApproveFlowChange 校验是否可变更分类
func CheckReportApproveFlowChange(reportType, classifyFirstId, classifySecondId int) (ok bool, err error) {
	var count int
	cond := ` AND classify_id_first = ? AND classify_id_second = ? AND state = ?`
	pars := make([]interface{}, 0)
	pars = append(pars, classifyFirstId, classifySecondId, models.ReportStateWaitApprove)
	switch reportType {
	case report_approve.FlowReportTypeChinese:
		ct, e := models.GetReportListCount(cond, pars, "")
		if e != nil {
			err = fmt.Errorf("GetReportListCount err: %s", e.Error())
			return
		}
		count = ct
	case report_approve.FlowReportTypeEnglish:
		ct, e := models.GetEnglishReportListCount(cond, pars, "")
		if e != nil {
			err = fmt.Errorf("GetEnglishReportListCount err: %s", e.Error())
			return
		}
		count = ct
	case report_approve.FlowReportTypeSmart:
		ob := new(smart_report.SmartReport)
		ct, e := ob.GetCountByCondition(cond, pars)
		if e != nil {
			err = fmt.Errorf("SmartReport GetCountByCondition err: %s", e.Error())
			return
		}
		count = ct
	default:
		err = fmt.Errorf("报告类型有误")
		return
	}
	if count <= 0 {
		ok = true
	}
	return
}

// CheckReportOpenApprove 校验报告是否开启了审批流
func CheckReportOpenApprove(reportType, firstId, secondId int) (opening bool, err error) {
	// 获取审批配置
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}
	openMap := map[string]bool{"false": false, "true": true}
	openApprove := openMap[confMap[models.BusinessConfIsReportApprove]]

	// 查询对应分类是否有审批流
	flowOb := new(report_approve.ReportApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, report_approve.ReportApproveFlowCols.ReportType, report_approve.ReportApproveFlowCols.ClassifyFirstId, report_approve.ReportApproveFlowCols.ClassifySecondId)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, reportType, firstId, secondId)
	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
	if e != nil && e.Error() != utils.ErrNoRow() {
		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
		return
	}

	// 开启审批/有审批流
	if openApprove && (flowItem != nil || confMap[models.BusinessConfReportApproveType] == models.BusinessConfReportApproveTypeOther) {
		opening = true
		return
	}
	return
}

// CheckReportCurrState 校验报告当前应有的状态
func CheckReportCurrState(reportType, firstId, secondId, operate int) (state int, err error) {
	// 获取审批配置
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}
	openMap := map[string]bool{"false": false, "true": true}
	openApprove := openMap[confMap[models.BusinessConfIsReportApprove]]

	// 查询对应分类是否有审批流
	flowOb := new(report_approve.ReportApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, report_approve.ReportApproveFlowCols.ReportType, report_approve.ReportApproveFlowCols.ClassifyFirstId, report_approve.ReportApproveFlowCols.ClassifySecondId)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, reportType, firstId, secondId)
	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
	if e != nil && e.Error() != utils.ErrNoRow() {
		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
		return
	}

	// 开启审批/有审批流
	if openApprove && (flowItem != nil || confMap[models.BusinessConfReportApproveType] == models.BusinessConfReportApproveTypeOther) {
		// 操作为无审批的操作时, 会转为有审批的初始状态-待提交
		stateMap := map[int]int{
			models.ReportOperateAdd:           models.ReportStateWaitSubmit,  // 新增
			models.ReportOperateEdit:          models.ReportStateWaitSubmit,  // 编辑
			models.ReportOperatePublish:       models.ReportStateWaitSubmit,  // 发布
			models.ReportOperateCancelPublish: models.ReportStateWaitSubmit,  // 取消发布
			models.ReportOperateSubmitApprove: models.ReportStateWaitApprove, // 提审
			models.ReportOperateCancelApprove: models.ReportStateWaitSubmit,  // 撤回
		}
		state = stateMap[operate]
		return
	}

	// 关闭审批/分类无审批
	// 操作为有审批的操作时, 会转为无审批的初始状态-未发布
	stateMap := map[int]int{
		models.ReportOperateAdd:           models.ReportStateUnpublished, // 新增
		models.ReportOperateEdit:          models.ReportStateUnpublished, // 编辑
		models.ReportOperatePublish:       models.ReportStatePublished,   // 发布
		models.ReportOperateCancelPublish: models.ReportStateUnpublished, // 取消发布
		models.ReportOperateSubmitApprove: models.ReportStateUnpublished, // 提审
		models.ReportOperateCancelApprove: models.ReportStateUnpublished, // 撤回
	}
	state = stateMap[operate]
	return
}

// SubmitReportApprove 提交审批
func SubmitReportApprove(reportType, reportId int, reportTitle string, firstId, secondId int, sysAdminId int, sysAdminName string) (approveId int, err error) {
	// 默认内部审批, 如果是走的第三方审批, 那么仅修改状态
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}
	openMap := map[string]bool{"false": false, "true": true}
	openApprove := openMap[confMap[models.BusinessConfIsReportApprove]]
	if !openApprove {
		err = fmt.Errorf("未开启审批")
		return
	}
	confApproveType := confMap[models.BusinessConfReportApproveType]
	if confApproveType == "" {
		confApproveType = models.BusinessConfReportApproveTypeEta
	}
	if confApproveType == models.BusinessConfReportApproveTypeOther {
		return
	}

	// 查询审批流
	flowOb := new(report_approve.ReportApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, report_approve.ReportApproveFlowCols.ReportType, report_approve.ReportApproveFlowCols.ClassifyFirstId, report_approve.ReportApproveFlowCols.ClassifySecondId)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, reportType, firstId, secondId)
	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
	if e != nil {
		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
		return
	}

	// 查询审批节点
	nodeOb := new(report_approve.ReportApproveNode)
	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, report_approve.ReportApproveNodeCols.ReportApproveFlowId, report_approve.ReportApproveNodeCols.CurrVersion)
	nodePars := make([]interface{}, 0)
	nodePars = append(nodePars, flowItem.ReportApproveFlowId, flowItem.CurrVersion)
	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
	if e != nil {
		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
		return
	}
	if len(nodeItems) == 0 {
		err = fmt.Errorf("无审批节点")
		return
	}

	// 取出首个节点
	firstNodeItem := new(report_approve.ReportApproveNode)
	for _, v := range nodeItems {
		if v.PrevNodeId == 0 {
			firstNodeItem = v
			continue
		}
	}
	if firstNodeItem == nil {
		err = fmt.Errorf("首个审批节点有误")
		return
	}

	// 审批信息
	now := time.Now().Local()
	newApprove := new(report_approve.ReportApprove)
	newApprove.ReportType = reportType
	newApprove.ReportId = reportId
	newApprove.ReportTitle = reportTitle
	newApprove.ClassifyFirstId = firstId
	newApprove.ClassifySecondId = secondId
	newApprove.State = report_approve.ReportApproveStateApproving
	newApprove.FlowId = flowItem.ReportApproveFlowId
	newApprove.FlowVersion = flowItem.CurrVersion
	newApprove.StartNodeId = firstNodeItem.ReportApproveNodeId
	newApprove.CurrNodeId = firstNodeItem.ReportApproveNodeId
	newApprove.ApplyUserId = sysAdminId
	newApprove.ApplyUserName = sysAdminName
	newApprove.CreateTime = now
	newApprove.ModifyTime = now
	if e = newApprove.Create(); e != nil {
		err = fmt.Errorf("生成审批信息失败, Err: %s", e.Error())
		return
	}
	approveId = newApprove.ReportApproveId

	// 生成节点审批记录
	err = BuildNextNodeRecordAndMsg(firstNodeItem, newApprove.ReportApproveId, sysAdminId, sysAdminName)
	return
}

// CancelReportApprove 撤回审批
func CancelReportApprove(reportType, reportId, approveId, sysAdminId int, sysAdminName string) (err error) {
	// 默认内部审批, 如果是走的第三方审批, 那么仅修改状态
	confMap, e := models.GetBusinessConf()
	if e != nil {
		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
		return
	}
	openMap := map[string]bool{"false": false, "true": true}
	openApprove := openMap[confMap[models.BusinessConfIsReportApprove]]
	if !openApprove {
		//err = fmt.Errorf("未开启审批")
		return
	}
	confApproveType := confMap[models.BusinessConfReportApproveType]
	if confApproveType == "" {
		confApproveType = models.BusinessConfReportApproveTypeEta
	}
	// 第三方审批仅修改报告状态
	if confApproveType == models.BusinessConfReportApproveTypeOther {
		e = updateReportApproveState(reportType, reportId, 0, models.ReportStateWaitSubmit)
		if e != nil {
			err = fmt.Errorf("更新报告审批撤回失败, Err: %s", e.Error())
			return
		}
		return
	}

	// 修改审批信息状态
	approveOb := new(report_approve.ReportApprove)
	approveItem, e := approveOb.GetItemById(approveId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			return
		}
		err = fmt.Errorf("approve GetItemById err: %s", e.Error())
		return
	}
	if approveItem.State == report_approve.ReportApproveStateCancel {
		return
	}
	approveItem.State = report_approve.ReportApproveStateCancel
	cols := []string{"State", "ModifyTime"}
	if e = approveItem.Update(cols); e != nil {
		err = fmt.Errorf("approve Update err: %s", e.Error())
		return
	}

	// 修改报告状态
	e = updateReportApproveState(reportType, reportId, 0, models.ReportStateWaitSubmit)
	if e != nil {
		err = fmt.Errorf("更新报告审批撤回失败, Err: %s", e.Error())
		return
	}

	// 推送撤回消息
	go func() {
		recordOb := new(report_approve.ReportApproveRecord)
		recordCond := fmt.Sprintf(` AND %s = ?`, report_approve.ReportApproveRecordCols.ReportApproveId)
		recordPars := make([]interface{}, 0)
		recordPars = append(recordPars, approveId)
		recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, "")
		if e != nil {
			utils.FileLog.Info(fmt.Sprintf("approve record GetItemsByCondition err: %s", e.Error()))
			return
		}

		messageOb := new(report_approve.ReportApproveMessage)
		messages := make([]*report_approve.ReportApproveMessage, 0)
		for _, v := range recordItems {
			m := new(report_approve.ReportApproveMessage)
			m.SendUserId = sysAdminId
			m.ReceiveUserId = v.ApproveUserId
			m.Content = fmt.Sprintf("%s提交的【研报审批】已撤回", sysAdminName)
			m.ReportApproveId = approveId
			m.ApproveState = report_approve.ReportApproveStateCancel
			m.CreateTime = time.Now().Local()
			m.ModifyTime = time.Now().Local()
			messages = append(messages, m)
		}
		e = messageOb.CreateMulti(messages)
		if e != nil {
			utils.FileLog.Info(fmt.Sprintf("CancelReportApprove messages err: %s", e.Error()))
			return
		}
	}()
	return
}

// updateReportApproveState 更新报告审批状态
func updateReportApproveState(reportType, reportId, approveId, state int) (err error) {
	updateCols := []string{"ApproveId", "State", "ModifyTime"}
	if reportType == report_approve.FlowReportTypeChinese {
		reportOb := new(models.Report)
		reportItem, e := reportOb.GetItemById(reportId)
		// 报告可能会被删除, 这里查不到就忽略掉
		if e != nil && e.Error() != utils.ErrNoRow() {
			err = fmt.Errorf("获取中文研报失败, Err: %s", e.Error())
			return
		}
		if reportItem != nil {
			reportItem.ApproveId = approveId
			reportItem.State = state
			reportItem.ModifyTime = time.Now().Local()
			if state == models.ReportStatePass || state == models.ReportStateRefused {
				updateCols = append(updateCols, "ApproveTime")
				reportItem.ApproveTime = time.Now().Local()
			}
			if state == models.ReportStatePass {
				updateCols = append(updateCols, "PublishTime")
				reportItem.PublishTime = time.Now().Local()
			}
			if e = reportItem.UpdateReport(updateCols); e != nil {
				err = fmt.Errorf("更新中文研报审批状态失败, Err: %s", e.Error())
				return
			}
		}
	}
	if reportType == report_approve.FlowReportTypeEnglish {
		reportItem, e := models.GetEnglishReportItemById(reportId)
		if e != nil && e.Error() != utils.ErrNoRow() {
			err = fmt.Errorf("获取英文研报失败, Err: %s", e.Error())
			return
		}
		if reportItem != nil {
			reportItem.ApproveId = approveId
			reportItem.State = state
			reportItem.ModifyTime = time.Now().Local()
			if state == models.ReportStatePass || state == models.ReportStateRefused {
				updateCols = append(updateCols, "ApproveTime")
				reportItem.ApproveTime = time.Now().Local()
			}
			if state == models.ReportStatePass {
				updateCols = append(updateCols, "PublishTime")
				reportItem.PublishTime = time.Now().Local()
			}
			if e = reportItem.UpdateReport(updateCols); e != nil {
				err = fmt.Errorf("更新英文研报审批状态失败, Err: %s", e.Error())
				return
			}
		}
	}
	if reportType == report_approve.FlowReportTypeSmart {
		reportOb := new(smart_report.SmartReport)
		reportItem, e := reportOb.GetItemById(reportId)
		if e != nil && e.Error() != utils.ErrNoRow() {
			err = fmt.Errorf("获取智能研报失败, Err: %s", e.Error())
			return
		}
		if reportItem != nil {
			reportItem.ApproveId = approveId
			reportItem.State = state
			reportItem.ModifyTime = time.Now().Local()
			if state == models.ReportStatePass || state == models.ReportStateRefused {
				updateCols = append(updateCols, "ApproveTime")
				reportItem.ApproveTime = time.Now().Local()
			}
			if state == models.ReportStatePass {
				updateCols = append(updateCols, "PublishTime")
				reportItem.PublishTime = time.Now().Local()
			}
			if e = reportItem.Update(updateCols); e != nil {
				err = fmt.Errorf("更新智能研报审批状态失败, Err: %s", e.Error())
				return
			}
		}
	}
	return
}

// PassReportApprove 通过审批
func PassReportApprove(approveItem *report_approve.ReportApprove, recordItem *report_approve.ReportApproveRecord, sysAdminId int, reportUrl string) (tips string, err error) {
	if approveItem == nil {
		err = fmt.Errorf("审批信息有误")
		return
	}
	if recordItem == nil {
		err = fmt.Errorf("审批记录有误")
		return
	}

	// 查询审批流和审批流节点
	flowOb := new(report_approve.ReportApproveFlow)
	flowItem, e := flowOb.GetItemById(approveItem.FlowId)
	if e != nil {
		err = fmt.Errorf("获取审批流失败, Err: %s", e.Error())
		return
	}
	nodeOb := new(report_approve.ReportApproveNode)
	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, report_approve.ReportApproveNodeCols.ReportApproveFlowId, report_approve.ReportApproveNodeCols.CurrVersion)
	nodePars := make([]interface{}, 0)
	nodePars = append(nodePars, flowItem.ReportApproveFlowId, flowItem.CurrVersion)
	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
	if e != nil {
		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
		return
	}
	if len(nodeItems) == 0 {
		err = fmt.Errorf("无审批节点")
		return
	}
	nodeMap := make(map[int]*report_approve.ReportApproveNode)
	for _, v := range nodeItems {
		nodeMap[v.ReportApproveNodeId] = v
	}

	// 取出审批记录的节点
	currNodeItem := nodeMap[recordItem.NodeId]
	if currNodeItem == nil {
		err = fmt.Errorf("当前节点信息有误")
		return
	}
	currNode, e := report_approve.FormatReportApproveNode2Item(currNodeItem)
	if e != nil {
		err = fmt.Errorf("当前节点信息有误, Err: %s", e.Error())
		return
	}
	now := time.Now().Local()
	recordItem.State = report_approve.ReportApproveStatePass
	recordItem.ApproveTime = now
	recordItem.ModifyTime = now
	recordCols := []string{"State", "ApproveTime", "ModifyTime"}
	lastApprove := false

	// 依次审批
	if currNode.ApproveType == report_approve.NodeApproveTypeRoll {
		if e = recordItem.Update(recordCols); e != nil {
			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
			return
		}

		// 检查依次审批情况
		sort.Slice(currNode.Users, func(k, j int) bool {
			return currNode.Users[k].Sort < currNode.Users[j].Sort
		})
		userLen := len(currNode.Users)
		//lastRoll := false
		nextUser := new(report_approve.ReportApproveNodeUserReq) // 下一个审批人, 为nil则表示当前审批人即为最后
		for k, v := range currNode.Users {
			// 当前审批人
			if v.UserId == sysAdminId && recordItem.ApproveUserSort == v.Sort {
				//if k == (userLen - 1) {
				//	lastRoll = true
				//	break
				//}
				if (k + 1) < userLen {
					nextUser = currNode.Users[k+1]
				}
			}
		}
		//if lastRoll && currNode.NextNodeId == 0 {
		//	lastApprove = true
		//}

		// 当前节点下一个审批人, 生成下一个审批记录且return
		if nextUser.UserId > 0 {
			newRecord := new(report_approve.ReportApproveRecord)
			newRecord.ReportApproveId = recordItem.ReportApproveId
			newRecord.State = report_approve.ReportApproveStateApproving
			newRecord.NodeId = currNode.ReportApproveNodeId
			newRecord.PrevNodeId = currNode.PrevNodeId
			newRecord.NextNodeId = currNode.NextNodeId
			newRecord.ApproveType = currNode.ApproveType
			newRecord.ApproveUserId = nextUser.UserId
			newRecord.ApproveUserName = nextUser.UserName
			newRecord.ApproveUserSort = nextUser.Sort
			newRecord.CreateTime = now
			newRecord.ModifyTime = now
			if e = newRecord.Create(); e != nil {
				err = fmt.Errorf("生成审批记录失败, Err: %s", e.Error())
				return
			}

			// 推送审批消息
			go func() {
				messageItem := new(report_approve.ReportApproveMessage)
				messageItem.SendUserId = approveItem.ApplyUserId
				messageItem.ReceiveUserId = nextUser.UserId
				messageItem.Content = "您有新的待办任务"
				messageItem.Remark = fmt.Sprintf("%s提交的【研报审批】需要您审批，请及时处理", approveItem.ApplyUserName)
				messageItem.ReportApproveId = approveItem.ReportApproveId
				messageItem.ApproveState = report_approve.ReportApproveStateApproving
				messageItem.CreateTime = now
				messageItem.ModifyTime = now
				if e = messageItem.Create(); e != nil {
					utils.FileLog.Info(fmt.Sprintf("PassReportApprove message err: %s", e.Error()))
					return
				}
			}()
			return
		}

		// 更新审批当前节点并进入下一个节点
		if currNode.NextNodeId > 0 {
			nextNode := nodeMap[currNode.NextNodeId]
			approveItem.CurrNodeId = currNode.NextNodeId
			approveItem.ModifyTime = now
			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
				return
			}
			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.ReportApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName)
			return
		} else {
			// 最后一个节点
			lastApprove = true
		}
	}

	// 会签
	if currNode.ApproveType == report_approve.NodeApproveTypeAll {
		// 查询其他审批人是否已审批
		otherOb := new(report_approve.ReportApproveRecord)
		otherCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, report_approve.ReportApproveRecordCols.ReportApproveId, report_approve.ReportApproveRecordCols.NodeId, report_approve.ReportApproveRecordCols.ApproveUserId)
		otherPars := make([]interface{}, 0)
		otherPars = append(otherPars, approveItem.ReportApproveId, recordItem.NodeId, sysAdminId)
		otherRecords, e := otherOb.GetItemsByCondition(otherCond, otherPars, []string{}, "")
		if e != nil {
			err = fmt.Errorf("获取节点审批记录失败, Err: %s", e.Error())
			return
		}
		otherPass := true
		for _, v := range otherRecords {
			if v.State != report_approve.ReportApproveStatePass {
				otherPass = false
			}
		}

		// 其他人未审批, 仅更新当前审批记录
		if e = recordItem.Update(recordCols); e != nil {
			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
			return
		}

		// 其他人已审批且为最后节点
		if otherPass && currNode.NextNodeId == 0 {
			lastApprove = true
		}

		// 其他人已审批且不为最后节点, 进入下一节点
		if otherPass && currNode.NextNodeId > 0 {
			nextNode := nodeMap[currNode.NextNodeId]
			approveItem.CurrNodeId = currNode.NextNodeId
			approveItem.ModifyTime = now
			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
				return
			}
			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.ReportApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName)
			return
		}
	}

	// 或签
	if currNode.ApproveType == report_approve.NodeApproveTypeAny {
		// 需检查一下审批的当前节点和记录的节点是否匹配, 不匹配可能是因为另外的审批人已通过, 所以此处应给提示
		// 前端也有做相应的判断，但是两个人同时进入审批详情页时就可能出现这种情况
		if approveItem.CurrNodeId != recordItem.NodeId {
			tips = "该节点已完成审批, 请刷新页面"
			return
		}

		if e = recordItem.Update(recordCols); e != nil {
			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
			return
		}
		if currNode.NextNodeId == 0 {
			lastApprove = true
		}
		if currNode.NextNodeId > 0 {
			nextNode := nodeMap[currNode.NextNodeId]
			approveItem.CurrNodeId = currNode.NextNodeId
			approveItem.ModifyTime = now
			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
				return
			}
			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.ReportApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName)
			return
		}
	}

	// 最后一个审批, 更新审批记录、审批、报告状态、推送消息给申请人
	if lastApprove {
		if e = recordItem.Update(recordCols); e != nil {
			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
			return
		}
		approveItem.State = report_approve.ReportApproveStatePass
		approveItem.ApproveTime = now
		approveItem.ModifyTime = now
		approveCols := []string{"State", "ApproveTime", "ModifyTime"}
		if e = approveItem.Update(approveCols); e != nil {
			err = fmt.Errorf("更新审批信息失败, Err: %s", e.Error())
			return
		}
		if e = updateReportApproveState(approveItem.ReportType, approveItem.ReportId, approveItem.ReportApproveId, models.ReportStatePass); e != nil {
			err = fmt.Errorf("更新报告审批状态失败, Err: %s", e.Error())
			return
		}

		go func() {
			messageItem := new(report_approve.ReportApproveMessage)
			messageItem.SendUserId = sysAdminId
			messageItem.ReceiveUserId = approveItem.ApplyUserId
			messageItem.Content = "您提交的审批已通过"
			messageItem.Remark = "您提交的【研报审批】已通过"
			messageItem.ReportApproveId = approveItem.ReportApproveId
			messageItem.ApproveState = report_approve.ReportApproveStatePass
			messageItem.CreateTime = now
			messageItem.ModifyTime = now
			if e = messageItem.Create(); e != nil {
				utils.FileLog.Info(fmt.Sprintf("PassReportApprove message err: %s", e.Error()))
				return
			}
		}()

		// 审批通过之后的处理
		go func() {
			if e = AfterReportApprovePass(approveItem.ReportType, approveItem.ReportId); e != nil {
				utils.FileLog.Info(fmt.Sprintf("AfterReportApprovePass err: %s, ReportType: %d, ReportId: %d", e.Error(), approveItem.ReportType, approveItem.ReportId))
				return
			}
		}()

		// 生成报告pdf和长图
		go Report2pdfAndJpeg(reportUrl, approveItem.ReportId, approveItem.ReportType)
	}
	return
}

// RefuseReportApprove 驳回审批
func RefuseReportApprove(approveItem *report_approve.ReportApprove, recordItem *report_approve.ReportApproveRecord, approveRemark string, sysAdminId int) (err error) {
	if approveItem == nil {
		err = fmt.Errorf("审批信息有误")
		return
	}
	if recordItem == nil {
		err = fmt.Errorf("审批记录有误")
		return
	}

	// 更新审批记录
	now := time.Now().Local()
	recordItem.State = report_approve.ReportApproveStateRefuse
	recordItem.ApproveRemark = approveRemark
	recordItem.ApproveTime = now
	recordItem.ModifyTime = now
	recordCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime"}
	if e := recordItem.Update(recordCols); e != nil {
		err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
		return
	}

	// 驳回-更新审批, 报告状态, 推送消息
	approveItem.State = report_approve.ReportApproveStateRefuse
	approveItem.ApproveRemark = approveRemark
	approveItem.ApproveTime = now
	approveItem.ModifyTime = now
	approveCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime"}
	if e := approveItem.Update(approveCols); e != nil {
		err = fmt.Errorf("更新审批状态失败, Err: %s", e.Error())
		return
	}
	if e := updateReportApproveState(approveItem.ReportType, approveItem.ReportId, approveItem.ReportApproveId, models.ReportStateRefused); e != nil {
		err = fmt.Errorf("更新报告状态失败, Err: %s", e.Error())
		return
	}

	// 推送驳回消息给申请人
	go func() {
		messageItem := new(report_approve.ReportApproveMessage)
		messageItem.SendUserId = sysAdminId
		messageItem.ReceiveUserId = approveItem.ApplyUserId
		messageItem.Content = "您提交的审批被驳回"
		messageItem.Remark = "您提交的【研报审批】已被驳回"
		messageItem.ReportApproveId = approveItem.ReportApproveId
		messageItem.ApproveState = report_approve.ReportApproveStateRefuse
		messageItem.CreateTime = now
		messageItem.ModifyTime = now
		if e := messageItem.Create(); e != nil {
			utils.FileLog.Info(fmt.Sprintf("ApproveReport message err: %s", e.Error()))
			return
		}
	}()
	return
}

// BuildNextNodeRecordAndMsg 生成下一个节点的审批记录并推送消息
func BuildNextNodeRecordAndMsg(approveNodeItem *report_approve.ReportApproveNode, approveId, sysAdminId int, sysAdminName string) (err error) {
	if approveNodeItem == nil {
		err = fmt.Errorf("approve node nil")
		return
	}

	// 根据节点审批方式生成审批记录
	now := time.Now().Local()
	approveNode, e := report_approve.FormatReportApproveNode2Item(approveNodeItem)
	if e != nil {
		err = fmt.Errorf("FormatReportApproveNode2Item err: %s", e.Error())
		return
	}
	if len(approveNode.Users) == 0 {
		err = fmt.Errorf("审批节点用户有误")
		return
	}
	newRecords := make([]*report_approve.ReportApproveRecord, 0)
	sort.Slice(approveNode.Users, func(k, j int) bool {
		return approveNode.Users[k].Sort < approveNode.Users[j].Sort
	})
	for _, u := range approveNode.Users {
		r := new(report_approve.ReportApproveRecord)
		r.ReportApproveId = approveId
		r.State = report_approve.ReportApproveStateApproving
		r.NodeId = approveNode.ReportApproveNodeId
		r.PrevNodeId = approveNode.PrevNodeId
		r.NextNodeId = approveNode.NextNodeId
		r.ApproveType = approveNode.ApproveType
		r.ApproveUserId = u.UserId
		r.ApproveUserName = u.UserName
		r.ApproveUserSort = u.Sort
		r.CreateTime = now
		r.ModifyTime = now
		newRecords = append(newRecords, r)
		// 依次审批仅生成一条记录
		if approveNode.ApproveType == report_approve.NodeApproveTypeRoll {
			break
		}
	}

	recordOb := new(report_approve.ReportApproveRecord)
	if e = recordOb.CreateMulti(newRecords); e != nil {
		err = fmt.Errorf("生成节点审批记录失败, Err: %s", e.Error())
		return
	}

	// 推送审批消息
	go func() {
		messageOb := new(report_approve.ReportApproveMessage)
		messages := make([]*report_approve.ReportApproveMessage, 0)
		for _, v := range newRecords {
			m := new(report_approve.ReportApproveMessage)
			m.SendUserId = sysAdminId
			m.ReceiveUserId = v.ApproveUserId
			m.Content = "您有新的待办任务"
			m.Remark = fmt.Sprintf("%s提交的【研报审批】需要您审批，请及时处理", sysAdminName)
			m.ReportApproveId = approveId
			m.ApproveState = report_approve.ReportApproveStateApproving
			m.CreateTime = now
			m.ModifyTime = now
			messages = append(messages, m)
		}
		e = messageOb.CreateMulti(messages)
		if e != nil {
			utils.FileLog.Info(fmt.Sprintf("BuildNextNodeRecordAndMsg messages err: %s", e.Error()))
			return
		}
	}()
	return
}

// AfterReportApprovePass 报告审批通过后的处理
func AfterReportApprovePass(reportType, reportId int) (err error) {
	// 中文研报
	if reportType == report_approve.FlowReportTypeChinese {
		report, e := models.GetReportById(reportId)
		if e != nil {
			if e.Error() == utils.ErrNoRow() {
				return
			}
			err = fmt.Errorf("获取研报信息失败, Err: %s", e.Error())
			return
		}
		_ = CreateVideo(report)
		_ = UpdateReportEs(report.Id, models.ReportStatePublished)

		return
	}

	// 英文研报
	if reportType == report_approve.FlowReportTypeEnglish {
		_ = UpdateEnglishReportEs(reportId, models.ReportStatePublished)
		return
	}

	// 智能研报
	if reportType == report_approve.FlowReportTypeSmart {
		ob := new(smart_report.SmartReport)
		item, e := ob.GetItemById(reportId)
		if e != nil {
			if e.Error() == utils.ErrNoRow() {
				return
			}
			err = fmt.Errorf("获取智能研报信息失败, Err: %s", e.Error())
			return
		}

		// 写入队列
		//var queue smart_report.Report2ImgQueueReq
		//queue.ReportType = 2
		//queue.ReportCode = item.ReportCode
		//_ = utils.Rc.LPush(utils.CACHE_CREATE_REPORT_IMGPDF_QUEUE, queue)

		// 生成音频
		if item.VideoUrl == "" {
			SmartReportBuildVideoAndUpdate(item)
		}

		// ES更新报告
		_ = SmartReportElasticUpsert(item.SmartReportId, models.ReportStatePublished)
	}
	return
}

// CheckCloseReportApproveConf 校验是否可以关闭报告审批
func CheckCloseReportApproveConf() (yes bool, err error) {
	// 查询待审批中的报告数量
	count, e := models.GetReportStateCount(models.ReportStateWaitApprove)
	if e != nil {
		err = fmt.Errorf("查询审批中的报告数量失败, Err: %s", e.Error())
		return
	}
	if count > 0 {
		return
	}
	count, e = models.GetEnglishReportStateCount(models.ReportStateWaitApprove)
	if e != nil {
		err = fmt.Errorf("查询审批中的英文报告数量失败, Err: %s", e.Error())
		return
	}
	if count > 0 {
		return
	}
	smartOb := new(smart_report.SmartReport)
	cond := ` AND state = ?`
	pars := make([]interface{}, 0)
	pars = append(pars, models.ReportStateWaitApprove)
	count, e = smartOb.GetCountByCondition(cond, pars)
	if e != nil {
		err = fmt.Errorf("查询审批中的智能报告数量失败, Err: %s", e.Error())
		return
	}
	if count > 0 {
		return
	}
	yes = true
	return
}

// FlowOperateResetReportState 审批流变化-重置报告的初始状态
func FlowOperateResetReportState(reportType, classifyFirstId, classifySecondId, oldState, State int) (err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("审批流变化-重置报告初始状态失败, ErrMsg: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 2)
		}
	}()

	// 中文研报
	if reportType == report_approve.FlowReportTypeChinese {
		e := models.UpdateReportsStateByCond(classifyFirstId, classifySecondId, oldState, State)
		if e != nil {
			err = fmt.Errorf("UpdateReportsStateByCond err: %s", e.Error())
		}
		return
	}

	// 英文研报
	if reportType == report_approve.FlowReportTypeEnglish {
		e := models.UpdateEnglishReportsStateByCond(classifyFirstId, classifySecondId, oldState, State)
		if e != nil {
			err = fmt.Errorf("UpdateEnglishReportsStateByCond err: %s", e.Error())
		}
		return
	}

	// 智能研报
	if reportType == report_approve.FlowReportTypeSmart {
		e := smart_report.UpdateSmartReportsStateByCond(classifyFirstId, classifySecondId, oldState, State)
		if e != nil {
			err = fmt.Errorf("UpdateSmartReportsStateByCond err: %s", e.Error())
		}
		return
	}
	return
}

// ConfigChangeResetReportState 审批配置变化-重置报告的初始状态
func ConfigChangeResetReportState(changeType string) (err error) {
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("审批配置变化-重置报告初始状态失败, ErrMsg: %s", err.Error())
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 2)
		}
	}()

	// 关闭审批-待提交->未发布
	if changeType == "" {
		e := models.UpdateReportsStateByCond(0, 0, models.ReportStateWaitSubmit, models.ReportStateUnpublished)
		if e != nil {
			err = fmt.Errorf("UpdateReportsStateByCond err: %s", e.Error())
		}
		e = models.UpdateEnglishReportsStateByCond(0, 0, models.ReportStateWaitSubmit, models.ReportStateUnpublished)
		if e != nil {
			err = fmt.Errorf("UpdateEnglishReportsStateByCond err: %s", e.Error())
		}
		e = smart_report.UpdateSmartReportsStateByCond(0, 0, models.ReportStateWaitSubmit, models.ReportStateUnpublished)
		if e != nil {
			err = fmt.Errorf("UpdateSmartReportsStateByCond err: %s", e.Error())
		}
		return
	}

	// 开启内部审批-未发布->部分待提交
	if changeType == models.BusinessConfReportApproveTypeEta {
		flowOb := new(report_approve.ReportApproveFlow)
		flows, e := flowOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
		if e != nil {
			err = fmt.Errorf("GetApproveFlows err: %s", e.Error())
			return
		}
		reportSecondIds, englishSecondIds, smartSecondIds := make([]int, 0), make([]int, 0), make([]int, 0)
		for _, v := range flows {
			if v.ReportType == report_approve.FlowReportTypeChinese {
				reportSecondIds = append(reportSecondIds, v.ClassifySecondId)
				continue
			}
			if v.ReportType == report_approve.FlowReportTypeEnglish {
				englishSecondIds = append(englishSecondIds, v.ClassifySecondId)
				continue
			}
			if v.ReportType == report_approve.FlowReportTypeSmart {
				smartSecondIds = append(smartSecondIds, v.ClassifySecondId)
			}
		}
		if len(reportSecondIds) > 0 {
			e = models.UpdateReportsStateBySecondIds(models.ReportStateUnpublished, models.ReportStateWaitSubmit, reportSecondIds)
			if e != nil {
				err = fmt.Errorf("UpdateReportsStateBySecondIds err: %s", e.Error())
				return
			}
		}
		if len(englishSecondIds) > 0 {
			e = models.UpdateEnglishReportsStateBySecondIds(models.ReportStateUnpublished, models.ReportStateWaitSubmit, englishSecondIds)
			if e != nil {
				err = fmt.Errorf("UpdateEnglishReportsStateBySecondIds err: %s", e.Error())
				return
			}
		}
		if len(smartSecondIds) > 0 {
			e = smart_report.UpdateSmartReportsStateBySecondIds(models.ReportStateUnpublished, models.ReportStateWaitSubmit, smartSecondIds)
			if e != nil {
				err = fmt.Errorf("UpdateSmartReportsStateBySecondIds err: %s", e.Error())
				return
			}
		}
		return
	}

	// 开启第三方审批->未发布->待提交
	if changeType == models.BusinessConfReportApproveTypeOther {
		e := models.UpdateReportsStateByCond(0, 0, models.ReportStateUnpublished, models.ReportStateWaitSubmit)
		if e != nil {
			err = fmt.Errorf("UpdateReportsStateByCond err: %s", e.Error())
		}
		e = models.UpdateEnglishReportsStateByCond(0, 0, models.ReportStateUnpublished, models.ReportStateWaitSubmit)
		if e != nil {
			err = fmt.Errorf("UpdateEnglishReportsStateByCond err: %s", e.Error())
		}
		e = smart_report.UpdateSmartReportsStateByCond(0, 0, models.ReportStateUnpublished, models.ReportStateWaitSubmit)
		if e != nil {
			err = fmt.Errorf("UpdateSmartReportsStateByCond err: %s", e.Error())
		}
		return
	}
	return
}
