package biapprove

import (
	"encoding/json"
	"eta_gn/eta_api/models"
	biapprove "eta_gn/eta_api/models/bi_approve"
	"eta_gn/eta_api/models/bi_approve/response"
	"eta_gn/eta_api/models/bi_dashboard"
	"eta_gn/eta_api/utils"
	"fmt"
	"sort"
	"strings"
	"time"
)

var (
	timeField   = map[int]string{1: fmt.Sprintf("a.%s", biapprove.BiApproveRecordCols.CreateTime), 2: fmt.Sprintf("a.%s", biapprove.BiApproveRecordCols.NodeApproveTime), 3: fmt.Sprintf("b.%s", biapprove.BiApproveCols.ApproveTime)}
	myTimeField = map[int]string{1: biapprove.BiApproveCols.CreateTime, 3: biapprove.BiApproveCols.ApproveTime}
	orderRules  = map[int]string{1: "ASC", 2: "DESC"}
)

func GetPulicBiClassifyList() (res []*bi_dashboard.BiDashboardClassifyItem, msg string, err error) {
	classifyList, err := bi_dashboard.GetBiDashboardClassifyAllList()
	if err != nil {
		msg = "获取公共分类列表失败"
		return
	}
	res = toClassifyItem(classifyList)
	return
}

func PassBiApprove(approveId int, adminId int) (msg string, err error) {
	approveItem, e := biapprove.GetBiApproveById(approveId)
	if e != nil {
		if utils.IsErrNoRow(e) {
			msg = "审批不存在, 请刷新页面"
			err = e
			return
		}
		msg = "操作失败"
		return
	}

	if approveItem.State != BiApproveStateApproving {
		msg = "审批状态有误, 请刷新页面"
		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
		return
	}

	var ApprovePars []interface{}
	Approveconds := ` AND bi_approve_id =? AND approve_user_id =? AND state =? `
	ApprovePars = append(ApprovePars, approveId, adminId, BiApproveStateApproving)

	recordItem, er := biapprove.GetBiApproveRecordByCondition(Approveconds, ApprovePars)
	if er != nil {
		if utils.IsErrNoRow(er) {
			msg = "无权审批"
			err = er
			return
		}
		msg = "操作失败"
		return
	}

	// 查询审批流和审批流节点
	flowItem, e := biapprove.GetBiApproveFlowById(approveItem.FlowId)
	if e != nil {
		err = fmt.Errorf("获取审批流失败, Err: %s", e.Error())
		return
	}
	nodePars := make([]interface{}, 0)
	nodeCond := ` AND bi_approve_flow_id =? AND curr_version =? `
	nodePars = append(nodePars, flowItem.BiApproveFlowId, flowItem.CurrVersion)
	nodeItems, e := biapprove.GetBiApproveNodeByCondition(nodeCond, nodePars)
	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]*biapprove.BiApproveNode)
	for _, v := range nodeItems {
		nodeMap[v.BiApproveNodeId] = v
	}

	// 取出审批记录的节点
	currNodeItem := nodeMap[recordItem.NodeId]
	if currNodeItem == nil {
		err = fmt.Errorf("当前节点信息有误")
		return
	}
	currNode, e := FormatBiApproveNode2Item(currNodeItem)
	if e != nil {
		err = fmt.Errorf("当前节点信息有误, Err: %s", e.Error())
		return
	}
	now := time.Now().Local()
	recordItem.State = BiApproveStatePass
	recordItem.ApproveTime = now
	recordItem.ModifyTime = now
	recordItem.NodeState = BiApproveStatePass
	recordItem.NodeApproveUserId = recordItem.ApproveUserId
	recordItem.NodeApproveUserName = recordItem.ApproveUserName
	recordItem.NodeApproveTime = now

	recordCols := []string{"State", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
	lastApprove := false

	// 依次审批
	if currNode.ApproveType == 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(response.BiApproveNodeUser) // 下一个审批人, 为nil则表示当前审批人即为最后
		for k, v := range currNode.Users {
			// 当前审批人
			if v.UserId == adminId && recordItem.ApproveUserSort == v.Sort {
				if (k + 1) < userLen {
					nextUser = currNode.Users[k+1]
				}
			}
		}
		// 当前节点下一个审批人, 生成下一个审批记录且return
		if nextUser.UserId > 0 {
			newRecord := new(biapprove.BiApproveRecord)
			newRecord.BiApproveId = recordItem.BiApproveId
			newRecord.State = BiApproveStateApproving
			newRecord.NodeId = currNode.BiApproveNodeId
			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
			newRecord.NodeState = BiApproveStateApproving
			if e = newRecord.Create(); e != nil {
				err = fmt.Errorf("生成审批记录失败, Err: %s", e.Error())
				return
			}

			// 推送审批消息
			go func() {
				messageItem := new(biapprove.BiApproveMessage)
				messageItem.SendUserId = approveItem.ApplyUserId
				messageItem.ReceiveUserId = nextUser.UserId
				messageItem.Content = "您有新的待办任务"
				messageItem.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", approveItem.ApplyUserName, approveItem.BiTitle)
				messageItem.BiApproveId = approveItem.BiApproveId
				messageItem.ApproveState = BiApproveStateApproving
				messageItem.CreateTime = now
				messageItem.ModifyTime = now
				if e = messageItem.Create(); e != nil {
					utils.FileLog.Info(fmt.Sprintf("PassBiApprove 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.BiApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.BiTitle)
			return
		} else {
			// 最后一个节点
			lastApprove = true
		}
	}

	// 会签
	if currNode.ApproveType == NodeApproveTypeAll {
		// 查询其他审批人是否已审批
		otherCond := ` AND bi_approve_id =? AND node_id =? AND approve_user_id <> ? `
		otherPars := make([]interface{}, 0)
		otherPars = append(otherPars, approveItem.BiApproveId, recordItem.NodeId, adminId)
		otherRecords, e := biapprove.GetBiApproveRecordItemsByCondition(otherCond, otherPars)
		if e != nil {
			err = fmt.Errorf("获取节点审批记录失败, Err: %s", e.Error())
			return
		}
		otherPass := true
		for _, v := range otherRecords {
			if v.State != BiApproveStatePass {
				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.BiApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.BiTitle)
			return
		}
	}

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

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

		// 将该审批的同一个节点的记录标记为已审批
		if e = recordItem.UpdateNodeState(recordItem.BiApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); 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.BiApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.BiTitle)
			return
		}
	}

	// 最后一个审批, 更新审批记录、审批、报告状态、推送消息给申请人
	if lastApprove {
		if e = recordItem.Update(recordCols); e != nil {
			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
			return
		}
		approveItem.State = BiApproveStatePass
		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 = updateBiApproveState(approveItem.BiId, BiStatePass); e != nil {
			err = fmt.Errorf("更新报告审批状态失败, Err: %s", e.Error())
			return
		}

		go func() {
			messageItem := new(biapprove.BiApproveMessage)
			messageItem.SendUserId = adminId
			messageItem.ReceiveUserId = approveItem.ApplyUserId
			messageItem.Content = "您提交的审批已通过"
			messageItem.Remark = fmt.Sprintf("您提交的【%s】已通过", approveItem.BiTitle)
			messageItem.BiApproveId = approveItem.BiApproveId
			messageItem.ApproveState = BiApproveStatePass
			messageItem.CreateTime = now
			messageItem.ModifyTime = now
			if e = messageItem.Create(); e != nil {
				utils.FileLog.Info(fmt.Sprintf("PassBiApprove message err: %s", e.Error()))
				return
			}
		}()
	}
	return

}

func toClassifyItem(src []*bi_dashboard.BiDashboardClassify) (dst []*bi_dashboard.BiDashboardClassifyItem) {
	for _, item := range src {
		dst = append(dst, &bi_dashboard.BiDashboardClassifyItem{
			BiDashboardClassifyId:   item.BiDashboardClassifyId,
			BiDashboardClassifyName: item.BiDashboardClassifyName,
		})
	}
	return
}

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

	// 根据节点审批方式生成审批记录
	now := time.Now().Local()
	approveNode, e := FormatBiApproveNode2Item(approveNodeItem)
	if e != nil {
		err = fmt.Errorf("FormatBiApproveNode2Item err: %s", e.Error())
		return
	}
	if len(approveNode.Users) == 0 {
		err = fmt.Errorf("审批节点用户有误")
		return
	}
	newRecords := make([]*biapprove.BiApproveRecord, 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(biapprove.BiApproveRecord)
		r.BiApproveId = approveId
		r.State = BiApproveStateApproving
		r.NodeId = approveNode.BiApproveNodeId
		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
		r.NodeState = BiApproveStateApproving // 当前节点审批状态
		newRecords = append(newRecords, r)
		// 依次审批仅生成一条记录
		if approveNode.ApproveType == NodeApproveTypeRoll {
			break
		}
	}

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

	// 推送审批消息
	go func() {
		messageOb := new(biapprove.BiApproveMessage)
		messages := make([]*biapprove.BiApproveMessage, 0)
		for _, v := range newRecords {
			m := new(biapprove.BiApproveMessage)
			m.SendUserId = sysAdminId
			m.ReceiveUserId = v.ApproveUserId
			m.Content = "您有新的待办任务"
			m.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", sysAdminName, biTitle)
			m.BiApproveId = approveId
			m.ApproveState = BiApproveStateApproving
			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
}

// updateBiApproveState 更新Bi看板审批状态
func updateBiApproveState(biId, state int) (err error) {
	// updateCols := []string{"ApproveId", "State", "ModifyTime"}
	updateCols := []string{"State", "ModifyTime"}
	BiItem, e := bi_dashboard.GetDashboardById(biId)
	if e != nil && !utils.IsErrNoRow(e) {
		err = fmt.Errorf("获取Bi看板失败, Err: %s", e.Error())
		return
	}
	if BiItem != nil && BiItem.BiDashboardId > 0 {
		// BiItem.ApproveId = approveId
		BiItem.State = state
		BiItem.ModifyTime = time.Now().Local()

		// if state == models.BiStatePass || state == models.BiStateRefused {
		// 	updateCols = append(updateCols, "ApproveTime")
		// 	// BiItem.ApproveTime = time.Now().Local()
		// }
		// if state == models.BiStatePass {
		// 	updateCols = append(updateCols, "PublishTime")
		// 	// BiItem.PublishTime = time.Now().Local()
		// }
		if e = BiItem.Update(updateCols); e != nil {
			err = fmt.Errorf("更新Bi看板审批状态失败, Err: %s", e.Error())
			return
		}
	}
	return
}

func ProcessingBiApprove(adminId, classifyId, timeType, sortField, sortRule, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.BiApproveItemOrmResp, respTotal int, msg string, err error) {
	cond := fmt.Sprintf(` AND a.%s = ? AND b.%s = ? AND a.%s = ?`, biapprove.BiApproveRecordCols.State, biapprove.BiApproveCols.State, biapprove.BiApproveRecordCols.ApproveUserId)
	pars := make([]interface{}, 0)
	pars = append(pars, BiApproveStateApproving, BiApproveStateApproving, adminId)
	order := ""

	// 筛选条件
	if classifyId > 0 {
		cond += fmt.Sprintf(` AND b.%s = ?`, biapprove.BiApproveCols.ClassifyId)
		pars = append(pars, classifyId)
	}
	if timeType <= 0 {
		timeType = 1
	}
	if timeType == 1 && startTime != "" && endTime != "" {
		_, e := time.Parse(utils.FormatDate, startTime)
		if e != nil {
			msg = "开始时间格式有误"
			err = e
			return
		}
		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
		if e != nil {
			msg = "结束时间格式有误"
			err = e
			return
		}
		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
		cond += fmt.Sprintf(` AND (b.%s BETWEEN ? AND ?)`, biapprove.BiApproveCols.CreateTime)
		pars = append(pars, startTime, tmpEndTime)
	}
	keyword = strings.TrimSpace(keyword)
	if keyword != "" {
		kw := fmt.Sprint("%", keyword, "%")
		cond += fmt.Sprintf(` AND b.%s LIKE ?`, biapprove.BiApproveCols.BiTitle)
		pars = append(pars, kw)
	}
	if sortField > 0 && sortRule > 0 {
		orderField := timeField[sortField]
		if orderField == "" {
			msg = "时间排序字段有误"
			return
		}
		orderRule := orderRules[sortRule]
		if orderRule == "" {
			msg = "时间排序方式有误"
			return
		}
		order = fmt.Sprintf("%s %s", orderField, orderRule)
	}
	total, e := biapprove.GetApprovingBiApproveCount(cond, pars)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApprovingBiApproveCount err: %s", e.Error())
		return
	}
	list, e := biapprove.GetApprovingBiApprovePageList(cond, pars, order, startSize, pageSize)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApprovingBiApprovePageList err: %s", e.Error())
		return
	}

	respList = toBiApproveItemOrmResp(list)
	respTotal = total
	return
}

// SolvedBiApprove 已处理的审批
func SolvedBiApprove(adminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.BiApproveItemOrmResp, respTotal int, msg string, err error) {
	cond := fmt.Sprintf(` AND a.%s = ? AND a.%s IN (?)`, biapprove.BiApproveRecordCols.ApproveUserId, biapprove.BiApproveRecordCols.NodeState)
	pars := make([]interface{}, 0)
	pars = append(pars, adminId, []int{BiApproveStatePass, BiApproveStateRefuse})
	order := ""

	// 筛选条件
	if classifyId > 0 {
		cond += fmt.Sprintf(` AND b.%s = ?`, biapprove.BiApproveCols.ClassifyId)
		pars = append(pars, classifyId)
	}
	if timeType > 0 && startTime != "" && endTime != "" {
		_, e := time.Parse(utils.FormatDate, startTime)
		if e != nil {
			msg = "开始时间格式有误"
			err = e
			return
		}
		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
		if e != nil {
			msg = "结束时间格式有误"
			err = e
			return
		}
		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, timeField[timeType])
		pars = append(pars, startTime, tmpEndTime)
	}
	keyword = strings.TrimSpace(keyword)
	if keyword != "" {
		kw := fmt.Sprint("%", keyword, "%")
		cond += fmt.Sprintf(` AND b.%s LIKE ?`, biapprove.BiApproveCols.BiTitle)
		pars = append(pars, kw)
	}
	if sortField > 0 && sortRule > 0 {
		orderField := timeField[sortField]
		if orderField == "" {
			msg = "时间排序字段有误"
			return
		}
		orderRule := orderRules[sortRule]
		if orderRule == "" {
			msg = "时间排序方式有误"
			return
		}
		order = fmt.Sprintf("%s %s", orderField, orderRule)
	}
	if approveState > 0 {
		cond += fmt.Sprintf(` AND a.%s = ?`, biapprove.BiApproveRecordCols.NodeState)
		pars = append(pars, approveState)
	}
	total, e := biapprove.GetApprovedBiApproveCount(cond, pars)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApprovedBiApproveCount err: %s", e.Error())
		return
	}
	list, e := biapprove.GetApprovedBiApprovePageList(cond, pars, order, startSize, pageSize)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApprovedBiApprovePageList err: %s", e.Error())
		return
	}

	for _, v := range list {
		// 这个时候的状态,用审批状态
		v.RecordState = v.NodeState
		v.ApproveTime = v.NodeApproveTime
	}
	respList = toBiApproveItemOrmResp(list)
	respTotal = total
	return
}

func MyApplyBiApproves(adminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.BiApproveItemOrmResp, respTotal int, msg string, err error) {
	cond := fmt.Sprintf(` AND a.%s = ?`, biapprove.BiApproveCols.ApplyUserId)
	pars := make([]interface{}, 0)
	pars = append(pars, adminId)
	order := ""

	// 筛选条件
	if classifyId > 0 {
		cond += fmt.Sprintf(` AND a.%s = ?`, biapprove.BiApproveCols.ClassifyId)
		pars = append(pars, classifyId)
	}
	if timeType > 0 && startTime != "" && endTime != "" {
		_, e := time.Parse(utils.FormatDate, startTime)
		if e != nil {
			msg = "开始时间格式有误"
			err = e
			return
		}
		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
		if e != nil {
			msg = "结束时间格式有误"
			err = e
			return
		}
		tmpEndTimeStr := tmpEndTime.AddDate(0, 0, 1).Format(utils.FormatDate)
		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, myTimeField[timeType])
		pars = append(pars, startTime, tmpEndTimeStr)
	}
	keyword = strings.TrimSpace(keyword)
	if keyword != "" {
		kw := fmt.Sprint("%", keyword, "%")
		cond += fmt.Sprintf(` AND a.%s LIKE ?`, biapprove.BiApproveCols.BiTitle)
		pars = append(pars, kw)
	}
	if sortField > 0 && sortRule > 0 {
		orderField := myTimeField[sortField]
		if orderField == "" {
			msg = "时间排序字段有误"
			return
		}
		orderRule := orderRules[sortRule]
		if orderRule == "" {
			msg = "时间排序方式有误"
			return
		}
		order = fmt.Sprintf("%s %s", orderField, orderRule)
	}
	if approveState > 0 {
		cond += fmt.Sprintf(` AND a.%s = ?`, biapprove.BiApproveRecordCols.State)
		pars = append(pars, approveState)
	}
	total, e := biapprove.GetApplyBiApproveCount(cond, pars)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApplyBiApproveCount err: %s", e.Error())
		return
	}
	respTotal = total
	list, e := biapprove.GetApplyBiApprovePageList(cond, pars, order, startSize, pageSize)
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetApplyBiApprovePageList err: %s", e.Error())
		return
	}
	respList = toBiApproveItemOrmResp(list)
	return
}

func GetApproveDetail(approveId int) (resp *response.BiApproveDetail, msg string, err error) {
	approveItem, e := biapprove.GetBiApproveById(approveId)
	if e != nil {
		if utils.IsErrNoRow(e) {
			msg = "审批已被删除, 请刷新页面"
			err = e
			return
		}
		msg = "获取失败"
		err = fmt.Errorf("GetItemById err: %s", e.Error())
		return
	}

	// 审批信息
	detail := new(response.BiApproveDetail)
	detail.Approve = new(response.BiApproveDetailItem)
	detail.Approve.BiApproveId = approveItem.BiApproveId
	detail.Approve.State = approveItem.State
	detail.Approve.FlowId = approveItem.FlowId
	detail.Approve.FlowVersion = approveItem.FlowVersion
	detail.Approve.StartNodeId = approveItem.StartNodeId
	detail.Approve.CurrNodeId = approveItem.CurrNodeId
	detail.Approve.ApplyUserId = approveItem.ApplyUserId
	detail.Approve.ApplyUserName = approveItem.ApplyUserName
	detail.Approve.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ApproveTime)
	detail.Approve.CreateTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.CreateTime)
	detail.Approve.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ModifyTime)

	// 审批节点
	nodeOb := new(biapprove.BiApproveNode)
	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, biapprove.BiApproveNodeCols.BiApproveFlowId, biapprove.BiApproveNodeCols.CurrVersion)
	nodePars := make([]interface{}, 0)
	nodePars = append(nodePars, approveItem.FlowId, approveItem.FlowVersion)
	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
		return
	}

	// 审批记录
	recordOb := new(biapprove.BiApproveRecord)
	recordCond := fmt.Sprintf(` AND %s = ?`, biapprove.BiApproveRecordCols.BiApproveId)
	recordPars := make([]interface{}, 0)
	recordPars = append(recordPars, approveItem.BiApproveId)
	recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, fmt.Sprintf("%s DESC", biapprove.BiApproveRecordCols.ApproveTime))
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
		return
	}
	recordMap := make(map[string]*biapprove.BiApproveRecord)
	for _, v := range recordItems {
		k := fmt.Sprintf("%d-%d", v.NodeId, v.ApproveUserId)
		recordMap[k] = v
	}

	// 审批流节点详情
	detail.ApproveFlowNodes = make([]*response.BiApproveDetailNodes, 0)
	for _, v := range nodeItems {
		t := new(response.BiApproveDetailNodes)
		t.BiApproveNodeId = v.BiApproveNodeId
		t.BiApproveFlowId = v.BiApproveFlowId
		t.PrevNodeId = v.PrevNodeId
		t.NextNodeId = v.NextNodeId
		t.NodeType = v.NodeType
		t.ApproveType = v.ApproveType
		t.Users = make([]*response.BiApproveDetailNodeUser, 0)
		us := make([]*response.BiApproveNodeUserReq, 0)
		if v.Users != "" {
			e = json.Unmarshal([]byte(v.Users), &us)
			if e != nil {
				msg = "获取失败"
				err = fmt.Errorf("json.Unmarshal err: %s", e.Error())
				return
			}
		}
		for _, vu := range us {
			u := new(response.BiApproveDetailNodeUser)
			u.UserType = vu.UserType
			u.UserId = vu.UserId
			u.UserName = vu.UserName
			u.Sort = vu.Sort
			// 审批记录
			k := fmt.Sprintf("%d-%d", v.BiApproveNodeId, vu.UserId)
			r := recordMap[k]
			if r != nil {
				u.ApproveRecord = new(response.BiApproveDetailNodeUserRecord)
				u.ApproveRecord.BiApproveRecordId = r.BiApproveRecordId
				u.ApproveRecord.State = r.State
				u.ApproveRecord.ApproveUserId = r.ApproveUserId
				u.ApproveRecord.ApproveUserName = r.ApproveUserName
				u.ApproveRecord.ApproveRemark = r.ApproveRemark
				u.ApproveRecord.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, r.ApproveTime)
			}
			t.Users = append(t.Users, u)
		}
		sort.Slice(t.Users, func(k, j int) bool {
			return t.Users[k].Sort < t.Users[j].Sort
		})
		detail.ApproveFlowNodes = append(detail.ApproveFlowNodes, t)
	}

	// 看板信息
	cnClassifyIdName := make(map[int]string)
	cnClassify, e := bi_dashboard.GetBiDashboardClassifyAllList()
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetBiDashboardClassifyAllList err: %s", e.Error())
		return
	}
	for _, v := range cnClassify {
		cnClassifyIdName[v.BiDashboardClassifyId] = v.BiDashboardClassifyName
	}
	detail.Bi = new(response.BiApproveDetailBi)
	detail.Bi.BiId = approveItem.BiId
	detail.Bi.BiTitle = approveItem.BiTitle
	detail.Bi.BiClassify = cnClassifyIdName[approveItem.ClassifyId]
	resp = detail
	return
}

func BiApproveRefuse(biApproveId, adminId int, approveRemark string) (msg string, err error) {
	approveItem, e := biapprove.GetBiApproveById(biApproveId)
	if e != nil {
		if utils.IsErrNoRow(e) {
			msg = "审批不存在, 请刷新页面"
			err = e
			return
		}
		msg = "操作失败"
		err = fmt.Errorf("GetBiApproveById err: %s", e.Error())
		return
	}
	if approveItem.State != BiApproveStateApproving {
		msg = "审批状态有误, 请刷新页面"
		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
		return
	}

	// 校验审批记录和审批
	recordOb := new(biapprove.BiApproveRecord)
	recordCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, biapprove.BiApproveRecordCols.BiApproveId, biapprove.BiApproveRecordCols.ApproveUserId, biapprove.BiApproveRecordCols.State)
	recordPars := make([]interface{}, 0)
	recordPars = append(recordPars, approveItem.BiApproveId, adminId, BiApproveStateApproving)
	recordItem, e := recordOb.GetItemByCondition(recordCond, recordPars, "")
	if e != nil {
		if utils.IsErrNoRow(e) {
			msg = "无权审批"
			err = e
			return
		}
		msg = "操作失败"
		err = fmt.Errorf("GetItemByCondition err: %s", e.Error())
		return
	}

	// 驳回审批
	if e = refuseBiApprove(approveItem, recordItem, approveRemark, adminId); e != nil {
		msg = "操作失败"
		err = fmt.Errorf("RefuseBiApprove err: %s", e.Error())
		return
	}
	return
}

// refuseBiApprove 驳回审批
func refuseBiApprove(approveItem *biapprove.BiApprove, recordItem *biapprove.BiApproveRecord, 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 = BiApproveStateRefuse
	recordItem.ApproveRemark = approveRemark
	recordItem.ApproveTime = now
	recordItem.ModifyTime = now

	recordItem.NodeState = BiApproveStateRefuse
	recordItem.NodeApproveUserId = recordItem.ApproveUserId
	recordItem.NodeApproveUserName = recordItem.ApproveUserName
	recordItem.NodeApproveTime = now

	recordCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
	if e := recordItem.Update(recordCols); e != nil {
		err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
		return
	}

	// 将该审批的同一个节点的记录标记为已审批
	if e := recordItem.UpdateNodeState(recordItem.BiApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); e != nil {
		err = fmt.Errorf("更新同一节点的其他审批记录状态失败, Err: %s", e.Error())
		return
	}

	// 驳回-更新审批, 报告状态, 推送消息
	approveItem.State = BiApproveStateRefuse
	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 := updateBiApproveState(approveItem.BiId, BiStateRefused); e != nil {
		err = fmt.Errorf("更新报告状态失败, Err: %s", e.Error())
		return
	}

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

func BiApproveCancel(biApproveId, adminId int, adminName string) (msg string, err error) {
	approveItem, e := biapprove.GetBiApproveById(biApproveId)
	if e != nil {
		if utils.IsErrNoRow(e) {
			msg = "审批已被删除, 请刷新页面"
			err = e
			return
		}
		msg = "操作失败"
		err = fmt.Errorf("GetBiApproveById err: %s", e.Error())
		return
	}
	if approveItem.ApplyUserId != adminId {
		msg = "非申请人不可撤销"
		err = fmt.Errorf("非申请人不可撤销")
		return
	}

	// 撤销审批
	e = cancelBiApprove(approveItem.BiId, approveItem.BiApproveId, adminId, adminName)
	if e != nil {
		msg = "操作失败"
		err = fmt.Errorf("cancelBiApprove err: %s", e.Error())
		return
	}
	return
}

// cancelBiApprove 撤回审批
func cancelBiApprove(biId, 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.BusinessConfIsBIApprove]]
	if !openApprove {
		//err = fmt.Errorf("未开启审批")
		return
	}

	// 修改审批信息状态
	approveItem, e := biapprove.GetBiApproveById(approveId)
	if e != nil {
		if utils.IsErrNoRow(e) {
			err = e
			return
		}
		err = fmt.Errorf("approve GetItemById err: %s", e.Error())
		return
	}
	if approveItem.State == BiApproveStateCancel {
		return
	}
	approveItem.State = BiApproveStateCancel
	approveItem.ModifyTime = time.Now()
	cols := []string{"State", "ModifyTime"}
	if e = approveItem.Update(cols); e != nil {
		err = fmt.Errorf("approve Update err: %s", e.Error())
		return
	}

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

	// 推送撤回消息
	go func() {
		recordOb := new(biapprove.BiApproveRecord)
		recordCond := fmt.Sprintf(` AND %s = ?`, biapprove.BiApproveRecordCols.BiApproveId)
		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(biapprove.BiApproveMessage)
		messages := make([]*biapprove.BiApproveMessage, 0)
		for _, v := range recordItems {
			m := new(biapprove.BiApproveMessage)
			m.SendUserId = sysAdminId
			m.ReceiveUserId = v.ApproveUserId
			m.Content = fmt.Sprintf("%s提交的【%s】已撤回", sysAdminName, approveItem.BiTitle)
			m.BiApproveId = approveId
			m.ApproveState = BiApproveStateCancel
			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("CancelBiApprove messages err: %s", e.Error()))
			return
		}
	}()
	return
}

// CheckBiOpenApprove 校验报告是否开启了审批流
func CheckBiOpenApprove(classifyId 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.BusinessConfIsBIApprove]]

	// 查询对应分类是否有审批流
	flowOb := new(biapprove.BiApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ?`, biapprove.BiApproveFlowCols.ClassifyId)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, classifyId)
	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
	if e != nil {
		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
		return
	}

	// 开启审批/有审批流
	if openApprove && (flowItem != nil) {
		opening = true
		return
	}
	return
}

// SubmitBiApprove 提交审批
func SubmitBiApprove(biId int, biTitle string, classifyId 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.BusinessConfIsBIApprove]]
	if !openApprove {
		err = fmt.Errorf("未开启审批")
		return
	}

	// 查询审批流
	flowOb := new(biapprove.BiApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ?`, biapprove.BiApproveFlowCols.ClassifyId)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, classifyId)
	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
	if e != nil {
		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
		return
	}

	// 查询审批节点
	nodeOb := new(biapprove.BiApproveNode)
	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, biapprove.BiApproveNodeCols.BiApproveFlowId, biapprove.BiApproveNodeCols.CurrVersion)
	nodePars := make([]interface{}, 0)
	nodePars = append(nodePars, flowItem.BiApproveFlowId, 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(biapprove.BiApproveNode)
	for _, v := range nodeItems {
		if v.PrevNodeId == 0 {
			firstNodeItem = v
			continue
		}
	}
	if firstNodeItem == nil {
		err = fmt.Errorf("首个审批节点有误")
		return
	}

	// 审批信息
	now := time.Now().Local()
	newApprove := new(biapprove.BiApprove)
	newApprove.BiId = biId
	newApprove.BiTitle = biTitle
	newApprove.ClassifyId = classifyId
	newApprove.State = BiApproveStateApproving
	newApprove.FlowId = flowItem.BiApproveFlowId
	newApprove.FlowVersion = flowItem.CurrVersion
	newApprove.StartNodeId = firstNodeItem.BiApproveNodeId
	newApprove.CurrNodeId = firstNodeItem.BiApproveNodeId
	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.BiApproveId

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

func toBiApproveItemOrmResp(src []*biapprove.BiApproveItemOrm) (res []*response.BiApproveItemOrmResp) {
	for _, v := range src {
		r := new(response.BiApproveItemOrmResp)
		r.BiApproveId = v.BiApproveId
		r.BiApproveRecordId = v.BiApproveRecordId
		r.BiId = v.BiId
		r.BiTitle = v.BiTitle
		r.ClassifyId = v.ClassifyId
		r.State = v.State
		r.RecordState = v.RecordState
		r.FlowId = v.FlowId
		r.FlowVersion = v.FlowVersion
		r.StartNodeId = v.StartNodeId
		r.CurrNodeId = v.CurrNodeId
		r.ApplyUserId = v.ApplyUserId
		r.ApplyUserName = v.ApplyUserName
		r.ApproveRemark = v.ApproveRemark
		r.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, v.ApproveTime)
		r.HandleTime = utils.TimeTransferString(utils.FormatDateTime, v.HandleTime)
		r.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
		r.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, v.ModifyTime)
		r.NodeState = v.NodeState
		res = append(res, r)
	}
	return
}

func GetBiClassifyAll() (list []*bi_dashboard.BiDashboardClassify, msg string, err error) {
	ClassifyList, e := bi_dashboard.GetBiDashboardClassifyAllList()
	if e != nil {
		msg = "获取失败"
		err = fmt.Errorf("GetBiDashboardClassifyAllList err: %s", e.Error())
		return
	}
	list = ClassifyList
	return
}

func CheckHasApprovingBi() (ok bool, err error) {
	count, err := biapprove.GetBiApproveCountByState(BiApproveStateApproving)
	if err != nil {
		return
	}
	if count > 0 {
		ok = true
	}
	return
}