package seal

import (
	"errors"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"hongze/hz_crm_api/models/company"
	"hongze/hz_crm_api/models/contract"
	"hongze/hz_crm_api/models/seal"
	"hongze/hz_crm_api/models/seal/request"
	"hongze/hz_crm_api/models/seal/response"
	"hongze/hz_crm_api/models/system"
	"hongze/hz_crm_api/services"
	"hongze/hz_crm_api/utils"
	"mime/multipart"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// UploadCheckBackFile 上传签回用印附件（实际操作）
func UploadCheckBackFile(sealId int, fileUrl string, opUser *system.Admin) (sealInfo *seal.Seal, err error) {
	//查询当前用印信息
	sealInfo, err = seal.GetSealInfoByContractId(sealId)
	if err != nil {
		return
	}

	//用印状态判断
	if sealInfo.Status != "已审批" && sealInfo.Status != "已签回" {
		err = errors.New("用印状态异常，不允许上传签回用印附件，当前用印状态：" + sealInfo.Status)
		return
	}
	sealInfo.CheckBackFileUrl = fileUrl
	sealInfo.Status = "已签回"
	sealInfo.ModifyTime = time.Now()
	sealInfo.CheckBackFileTime = time.Now()
	err = sealInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
	if err != nil {
		return
	}

	// 给销售发送模版消息
	sellerInfo, tErr := system.GetSysAdminById(sealInfo.UserId)
	if tErr == nil {
		if sellerInfo.Mobile != "" {
			go services.SendSealFinishedWxTemplateMsg(sellerInfo.Mobile, sealInfo.CompanyName, sealInfo.SealId)
		}
	}
	return
}

// UploadCheckBackFileFromSeal 用印上传签回用印附件
func UploadCheckBackFileFromSeal(sealId int, ext string, fileMulti multipart.File, opUser *system.Admin) (sealInfo *seal.Seal, err error) {
	//查询当前用印信息
	sealInfo, err = seal.GetSealInfoById(sealId)
	if err != nil {
		return
	}

	//用印状态判断
	if sealInfo.Status != "已审批" && sealInfo.Status != "已签回" {
		err = errors.New("用印状态异常，不允许上传签回用印附件，当前用印状态：" + sealInfo.Status)
		return
	}

	fileName := ``
	//保存的文件名
	fileName = sealInfo.CompanyName + "_" + sealInfo.Code + "（签回）"
	if sealInfo.ContractId > 0 {
		//获取合同信息
		contractInfo, tmpErr := contract.GetContractById(sealInfo.ContractId)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		//保存的文件名
		fileName = contractInfo.CompanyName + "_" + contractInfo.ContractCode + "（签回）"
	}
	//非正式环境下，文件名上面还是加上随机数
	if utils.RunMode != "release" {
		fileName += "_" + utils.GetRandStringNoSpecialChar(10)
	}
	fileName += ext
	//上传到阿里云
	resourceUrl, err := services.UploadToOssAndFileName(fileMulti, fileName)
	if err != nil {
		err = errors.New("文件保存失败,Err:" + err.Error())
		return
	}
	sealInfo.CheckBackFileUrl = resourceUrl
	sealInfo.Status = "已签回"
	sealInfo.ModifyTime = time.Now()
	sealInfo.CheckBackFileTime = time.Now()
	err = sealInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
	if err != nil {
		return
	}
	// 给销售发送模版消息
	sellerInfo, tErr := system.GetSysAdminById(sealInfo.UserId)
	if tErr == nil {
		if sellerInfo.Mobile != "" {
			go services.SendSealFinishedWxTemplateMsg(sellerInfo.Mobile, sealInfo.CompanyName, sealInfo.SealId)
		}
	}
	return
}

// ApplySeal 申请用印
func ApplySeal(sysUser *system.Admin, req request.SealApprovalApplyReq) (err error) {
	o := orm.NewOrm()
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()

	// 添加用印
	sealInfo, err := addSeal(sysUser.AdminId, req.ContractId, req.FileNum, sysUser.RealName, req.Use, req.CompanyName, req.UseCompanyName, req.CreditCode, req.ServiceType, req.SealType, req.Remark, req.FileUrls)
	if err != nil {
		return
	}

	// 添加操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, sysUser.AdminId, 0, "apply", sysUser.RealName, "提交审批", "")
	if err != nil {
		return
	}

	// 用印审批
	err = SubmitApproval(sealInfo)
	return
}

// addSeal 新增用印
func addSeal(userId, contractId, fileNum int, userName, use, companyName, useCompanyName, creditCode, serviceType, sealType, remark string, fileUrls []string) (sealInfo *seal.Seal, err error) {
	if !strings.Contains(strings.Join(seal.EnumUse, ","), use) {
		err = errors.New("用印用途异常")
		return
	}
	if !strings.Contains(strings.Join(seal.EnumServiceType, ","), serviceType) {
		err = errors.New("业务类型异常")
		return
	}

	sealCode, err := seal.GetSealCode()
	if err != nil {
		return
	}
	fileUrl := ""
	now := time.Now()
	attachments := make([]*seal.Attachment, 0)
	if len(fileUrls) == 1 {
		fileUrl = fileUrls[0]
	}
	sealInfo = &seal.Seal{
		Code:           sealCode,
		UserId:         userId,
		UserName:       userName,
		Use:            use,
		CompanyName:    companyName,
		UseCompanyName: useCompanyName,
		CreditCode:     creditCode,
		ServiceType:    serviceType,
		SealType:       sealType,
		Status:         "待提交",
		Remark:         remark,
		FileUrl:        fileUrl,
		FileNum:        fileNum,
		ContractId:     contractId,
		ModifyTime:     now,
		CreateTime:     now,
	}
	err = seal.AddSeal(sealInfo)
	if err != nil {
		return
	}
	if len(fileUrls) > 1 {
		for _, v := range fileUrls {
			tmp := &seal.Attachment{
				SealId:     sealInfo.SealId,
				FileUrl:    v,
				ModifyTime: now,
				CreateTime: now,
			}
			attachments = append(attachments, tmp)
		}
		err = seal.AddAttachments(attachments)
	}
	return
}

// EditApply 编辑用印审批
func EditApply(sysUser *system.Admin, req request.SealApprovalEditReq) (err error) {
	o := orm.NewOrm()
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()

	// 编辑用印
	sealInfo, err := editSeal(req.SealId, sysUser.AdminId, req.ContractId, req.FileNum, req.Use, req.CompanyName, req.UseCompanyName, req.CreditCode, req.ServiceType, req.SealType, req.Remark, req.FileUrls)
	if err != nil {
		return
	}

	// 添加操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, sysUser.AdminId, 0, "edit", sysUser.RealName, "重提审批", "")
	if err != nil {
		return
	}

	// 用印审批
	err = SubmitApproval(sealInfo)
	return
}

// editSeal 编辑用印申请
func editSeal(sealId, userId, contractId, fileNum int, use, companyName, userCompanyName, creditCode, serviceType, sealType, remark string, fileUrls []string) (sealInfo *seal.Seal, err error) {
	if !strings.Contains(strings.Join(seal.EnumUse, ","), use) {
		err = errors.New("用印用途异常")
		return
	}
	if !strings.Contains(strings.Join(seal.EnumServiceType, ","), serviceType) {
		err = errors.New("业务类型异常")
		return
	}

	sealInfo, err = seal.GetSealInfoById(sealId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			err = errors.New("获取用印申请失败")
		}
		return
	}
	if sealInfo.UserId != userId {
		err = errors.New("当前账号无操作权限")
		return
	}
	ignoreStatus := []string{"待提交", "已撤回", "已驳回"}
	if !strings.Contains(strings.Join(ignoreStatus, ","), sealInfo.Status) {
		err = errors.New("用印状态异常，不允许修改，当前用印状态：" + sealInfo.Status)
		return
	}

	fileUrl := ""
	now := time.Now()
	attachments := make([]*seal.Attachment, 0)
	if len(fileUrls) == 1 {
		fileUrl = fileUrls[0]
	}
	sealInfo.Use = use
	sealInfo.CompanyName = companyName
	sealInfo.UseCompanyName = userCompanyName
	sealInfo.CreditCode = creditCode
	sealInfo.ServiceType = serviceType
	sealInfo.SealType = sealType
	sealInfo.Remark = remark
	sealInfo.FileUrl = fileUrl
	sealInfo.FileNum = fileNum
	sealInfo.ContractId = contractId
	sealInfo.ModifyTime = now
	sealInfo.CreateTime = now // 更新提交时间
	sealInfo.Status = "待提交"
	err = sealInfo.Update([]string{"Use", "CompanyName", "UseCompanyName", "CreditCode", "ServiceType", "SealType", "Remark", "FileUrl", "FileNum", "ContractId", "ModifyTime", "CreateTime", "Status"})
	if err != nil {
		return
	}
	//删除原有的附件，新增最新的附件
	err = seal.DelAttachmentBySealId(sealId)
	if err != nil {
		return
	}
	if len(fileUrls) > 1 {
		for _, v := range fileUrls {
			tmp := &seal.Attachment{
				SealId:     sealInfo.SealId,
				FileUrl:    v,
				ModifyTime: now,
				CreateTime: now,
			}
			attachments = append(attachments, tmp)
		}
		err = seal.AddAttachments(attachments)
	}
	return
}

// VerifierEditApply 合规编辑用印申请
func VerifierEditApply(sysUser *system.Admin, req request.SealApprovalEditReq) (err error) {
	// 审批权限校验
	sealInfo, approvalInfo, approvalRecord, err := CheckApprovalAuth(req.SealId, sysUser)
	if err != nil {
		return
	}

	// 数据状态校验
	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE {
		err = errors.New("当前账号无修改权限")
		return
	}
	if sealInfo.Status != "待审批" {
		err = errors.New("用印状态异常，不允许修改，当前用印状态：" + sealInfo.Status)
		return
	}
	if !strings.Contains(strings.Join(seal.EnumUse, ","), req.Use) {
		err = errors.New("用印用途异常")
		return
	}
	if !strings.Contains(strings.Join(seal.EnumServiceType, ","), req.ServiceType) {
		err = errors.New("业务类型异常")
		return
	}
	// 变更字段判断
	updateCol := make([]string, 0)
	updateContent := make([]string, 0)
	if sealInfo.Use != req.Use {
		updateCol = append(updateCol, "Use")
		updateContent = append(updateContent, "用印用途")
	}
	if sealInfo.SealType != req.SealType {
		updateCol = append(updateCol, "SealType")
		updateContent = append(updateContent, "加盖何种印章")
	}
	if sealInfo.Remark != req.Remark {
		updateCol = append(updateCol, "Remark")
		updateContent = append(updateContent, "备注")
	}
	if sealInfo.FileNum != req.FileNum {
		updateCol = append(updateCol, "FileNum")
		updateContent = append(updateContent, "文件份数")
	}
	//判断附件地址是否相等：
	sealAttachements, err := seal.GetAttachmentBySealId(sealInfo.SealId)
	if err != nil {
		err = errors.New(fmt.Sprint("获取用印附件失败,Err:"+err.Error(), err))
		return
	}
	oldFileUrls := make([]string, 0)
	if sealInfo.FileUrl != "" {
		oldFileUrls = append(oldFileUrls, sealInfo.FileUrl)
	}
	if len(sealAttachements) > 0 {
		for _, v := range sealAttachements {
			oldFileUrls = append(oldFileUrls, v.FileUrl)
		}
	}
	attachmentFlag := false
	if !reflect.DeepEqual(oldFileUrls, req.FileUrls) {
		updateCol = append(updateCol, "FileUrl")
		updateContent = append(updateContent, "文件附件")
		attachmentFlag = true
	}
	if len(updateCol) <= 0 {
		err = errors.New("没有变更信息")
		return
	}
	content := "用印修改：" + sysUser.RealName + "修改了" + strings.Join(updateContent, "、")
	// 通过盖章类型判断是否需要变更审批流程
	originFlowType := GetFlowTypeBySealType(sealInfo.SealType)
	reqFlowType := GetFlowTypeBySealType(req.SealType)
	//如果变更了盖章类型（涉及到审批流程变更），那么需要变更审批流
	//变更审批流：先驳回用印申请，再修改用印，再发消息给申请人，再替申请人重新发起申请，
	//然后遍历审批流程，当前操作人节点之前的全部审核通过，最后通过当前操作人的节点（改成如果一级审批人如果是自己，那么直接通过这一级审批，否则不通过，让审批单重走流程）
	newFileUrl := ""
	if len(req.FileUrls) == 1 {
		newFileUrl = req.FileUrls[0]
	}
	if originFlowType != reqFlowType {
		// 先驳回
		err = reject(sealInfo, approvalInfo, approvalRecord, sysUser, "")
		if err != nil {
			return
		}
		//修改用印申请，给申请人发消息
		sealInfo.Use = req.Use
		sealInfo.SealType = req.SealType
		sealInfo.Remark = req.Remark
		sealInfo.FileNum = req.FileNum
		sealInfo.FileUrl = newFileUrl
		sealInfo.ModifyTime = time.Now()
		verifierEdit(sealInfo, updateCol, approvalRecord.ContractApprovalRecordId, content, sysUser, attachmentFlag, req.FileUrls)
		// 重新获取最新的用印单
		sealInfo, tmpErr := seal.GetSealInfoById(sealInfo.SealId)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		err = reapply(sealInfo, sysUser)
		if err != nil {
			return
		}
		// 重新发起申请
	} else {
		// 修改用印申请，给申请人发消息
		sealInfo.Use = req.Use
		sealInfo.SealType = req.SealType
		sealInfo.Remark = req.Remark
		sealInfo.FileNum = req.FileNum
		sealInfo.FileUrl = newFileUrl
		sealInfo.ModifyTime = time.Now()
		verifierEdit(sealInfo, updateCol, approvalRecord.ContractApprovalRecordId, content, sysUser, attachmentFlag, req.FileUrls)
		// 审核通过
		err = ApprovedApproval(sealInfo.SealId, sysUser, "")
	}
	// 操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, sysUser.AdminId, approvalRecord.ContractApprovalRecordId, "edit", sysUser.RealName, "审批人修改信息", "")
	if err != nil {
		return
	}

	return
}

// verifierEdit 审批人修改用印信息
func verifierEdit(sealInfo *seal.Seal, updateCol []string, approvalRecordId int, content string, opUser *system.Admin, attachmentFlag bool, fileUrls []string) {
	if attachmentFlag {
		// 同时更新用印申请和附件
		_ = updateSealAndAttachment(sealInfo, updateCol, fileUrls)
	} else {
		_ = sealInfo.Update(updateCol)
	}

	//给用印人，发送修改消息
	sysUserMobile := ""
	sysUser, _ := system.GetSysAdminById(opUser.AdminId)
	if sysUser != nil {
		sysUserMobile = sysUser.Mobile
	}
	go services.AddCompanyApprovalMessage(opUser.AdminId, sealInfo.UserId, 0, approvalRecordId, 3, sourceType, 2, sealInfo.CompanyName, content, content, sysUserMobile)

	return
}

// reapply 重新提交审批单
func reapply(sealInfo *seal.Seal, opUser *system.Admin) (err error) {
	// 发起审批
	approvalInfo, contractApprovalRecordList, err := addApproval(sealInfo)
	if err != nil {
		return
	}

	// 校验一级审批人是否与当前提交人一致，如果一致的话，那么审批通过且不发送消息给一级审批人
	var contractApprovalRecord *contract.ContractApprovalRecord
	for _, tmpContractApprovalRecord := range contractApprovalRecordList {
		if tmpContractApprovalRecord.NodeId == approvalInfo.CurrNodeId && tmpContractApprovalRecord.ApproveUserId == opUser.AdminId {
			contractApprovalRecord = tmpContractApprovalRecord
		}
	}

	// 如果一级审批人和当前提交人一致，那么审批通过，且不发送消息给一级审批人
	if contractApprovalRecord != nil {
		err = ApprovedApproval(sealInfo.SealId, opUser, "")
	} else {
		//如果一级审批人和当前提交人不一致，那么发送消息给一级审批人，重走审批流程
		//待办通知
		{
			//发送消息下级审批人
			go MessageToNodeUser(contractApprovalRecordList[0].NodeId, approvalInfo.ApplyUserId, approvalInfo.ContractApprovalId, 1, 1, sealInfo.CompanyName, sealInfo.Use)
		}
	}

	return
}

// GetSealApprovalPageList 获取用印审批分页列表
func GetSealApprovalPageList(condition, joinCondition string, pars []interface{}, startSize, pageSize int, sysUser *system.Admin) (newList []*response.SealApprovalList, total int, err error) {
	// 1.列表数据
	list, total, err := seal.GetSealApprovalListByWhere(condition, joinCondition, pars, startSize, pageSize)
	if err != nil {
		err = errors.New(fmt.Sprint("获取用印审批列表失败,Err:"+err.Error(), err))
		return
	}

	// 2.操作权限
	if len(list) > 0 {
		// 取出所有列表最新的审批IDs
		approvalIdSlice := make([]string, 0)
		// 取出所有列表的关联合同id
		contractIdSlice := make([]string, 0)
		for i := 0; i < len(list); i++ {
			approvalIdSlice = append(approvalIdSlice, strconv.Itoa(list[i].ContractApprovalId))
			contractIdSlice = append(contractIdSlice, strconv.Itoa(list[i].ContractId))
		}
		approvalIdStr := strings.Join(approvalIdSlice, ",")

		// 通过审批IDs获取所有的审批流
		approvalRecordList, tempErr := contract.GetContractApprovalRecordListByContractApprovalIds(approvalIdStr)
		//approvalRecordList, tempErr := contract.GetContractApprovalRecordList(approvalIdStr, sysUser.AdminId)
		if tempErr != nil {
			err = errors.New(fmt.Sprint("获取审批流失败,Err:"+tempErr.Error(), err))
			return
		}

		// 获取自己的审批流列表数据
		selfContractApprovalRecordList, tempErr := contract.GetSelfContractApprovalRecordList(approvalIdStr, sysUser.AdminId)
		if tempErr != nil {
			err = errors.New(fmt.Sprint("获取审批列表失败，Err:"+tempErr.Error(), err))
			return
		}
		selfContractApprovalRecordMap := make(map[int]*contract.ContractApprovalRecord)
		for i := 0; i < len(selfContractApprovalRecordList); i++ {
			selfContractApprovalRecordMap[selfContractApprovalRecordList[i].ContractApprovalId] = selfContractApprovalRecordList[i]
		}

		// 获取所有关联的合同列表
		selfContractMap := make(map[int]*contract.ContractList)
		{
			if len(contractIdSlice) > 0 {
				contractIdStr := strings.Join(contractIdSlice, ",")
				contractList, tempErr := contract.GetContractListByContractIds(contractIdStr)
				if tempErr != nil {
					err = errors.New(fmt.Sprint("获取合同失败,Err:"+tempErr.Error(), err))
					return
				}
				for i := 0; i < len(contractList); i++ {
					selfContractMap[contractList[i].ContractId] = contractList[i]
				}
			}
		}

		for i := 0; i < len(list); i++ {
			item := list[i]
			list[i].CreateTimeStr = item.CreateTime.Format(utils.FormatDateTime)
			list[i].ModifyTimeStr = item.ModifyTime.Format(utils.FormatDateTime)
			list[i].ApproveTimeStr = item.ApproveTime.Format(utils.FormatDateTime)
			list[i].InvalidTimeStr = item.InvalidTime.Format(utils.FormatDateTime)
			list[i].CheckBackFileTimeStr = item.CheckBackFileTime.Format(utils.FormatDateTime)

			if item.ApproveStatus == "已审批" || item.ApproveStatus == "已驳回" {
				list[i].ApproveTime = item.ModifyTime
				list[i].ApproveTimeStr = item.ModifyTime.Format(utils.FormatDateTime)
			}

			// 如果当前状态是待审批的话，那么校验自己的审批流数据，然后去返回对应的状态
			if item.Status == "待审批" {
				// 如果是自己发起的审批单，同时已经经过了一轮审批，那么标记为处理中
				if item.ApplyUserId == sysUser.AdminId && item.CurrNodeId > item.StartNodeId {
					list[i].Status = "处理中"
				} else if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN && item.CurrNodeId > item.StartNodeId {
					// 如果是超管角色，同时已经经过了一轮审批，那么标记为处理中
					list[i].Status = "处理中"
				} else {
					// 此处可能出现同一审批人同时有权限处理一级二级的情况
					maxNodeId := 0
					tempStatus := "待审批"
					for _, selfRecord := range selfContractApprovalRecordList {
						if item.ContractApprovalId == selfRecord.ContractApprovalId {
							if selfRecord.NodeId > maxNodeId {
								maxNodeId = selfRecord.NodeId
							}
							if maxNodeId < item.CurrNodeId && selfRecord.NodeType != "cc" {
								tempStatus = "处理中"
							} else if maxNodeId == item.CurrNodeId && selfRecord.NodeType != "cc" {
								tempStatus = "待审批"
							}
						}
					}
					list[i].Status = tempStatus
					/*if contractApprovalRecord, has := selfContractApprovalRecordMap[item.ContractApprovalId]; has {
						if contractApprovalRecord.NodeId < item.CurrNodeId && contractApprovalRecord.NodeType != "cc" {
							list[i].Status = "处理中"
						}
					}*/
				}
			}

			// 合同编码
			if selfContract, has := selfContractMap[item.ContractId]; has {
				list[i].ContractCode = selfContract.ContractCode
			}

			// 取出item对应approval_id的审批流
			var tempApprovalRecordMap []*contract.ContractApprovalRecord
			for _, recordItem := range approvalRecordList {
				if item.ContractApprovalId == recordItem.ContractApprovalId {
					tempApprovalRecordMap = append(tempApprovalRecordMap, recordItem)
				}
			}
			// 获取对该条数据的操作权限
			opButton, tempErr := handleListOpButton(item, tempApprovalRecordMap, sysUser)
			if tempErr != nil {
				err = errors.New(fmt.Sprint("获取操作权限失败,Err:"+tempErr.Error(), err))
				return
			}

			tempNewList := &response.SealApprovalList{
				SealApprovalItem: item,
				OpButton:         opButton,
			}
			newList = append(newList, tempNewList)
		}
	}

	return
}

// handleOpButton 列表数据操作权限
func handleListOpButton(approvalItem *seal.SealApprovalItem, recordList []*contract.ContractApprovalRecord, sysUser *system.Admin) (opButton response.SealApprovalOpButton, err error) {
	// 待审批状态下，如果是自己发起的审批单，同时已经经过了一轮审批，那么标记为处理中
	if approvalItem.Status == "待审批" {
		if approvalItem.ApplyUserId == sysUser.AdminId && approvalItem.CurrNodeId > approvalItem.StartNodeId {
			approvalItem.Status = "处理中"
		}
	}

	flowNodeMap := make(map[int][]contract.ContractApprovalRecord, 0)
	keySort := make([]int, 0)
	for _, approvalRecord := range recordList {
		// 如果当前节点正好是该节点，同时审批单状态是待审批状态，然后当前账号又有权限，该账号也正是审批人，那么允许审批操作
		if approvalItem.CurrNodeId == approvalRecord.NodeId && approvalItem.Status == "待审批" {
			if sysUser.AdminId == approvalRecord.ApproveUserId && approvalRecord.NodeType == "check" {
				opButton.Approval = true
			}
			// 合规在审批过程中具有 部分修改权限
			if sysUser.AdminId == approvalRecord.ApproveUserId && sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && approvalRecord.NodeType == "check" {
				opButton.CheckEdit = true
			}
		}
		// 如果当前节点正好是该节点，同时审批单状态又是第一层节点
		if approvalItem.CurrNodeId == approvalRecord.NodeId && approvalRecord.PrevNodeId == 0 && approvalItem.Status == "待审批" {
			// 发起人具有撤回审批单权限
			if sysUser.AdminId == approvalItem.ApplyUserId {
				opButton.Cancel = true
			}
		}
		if tmpFlowNodeList, ok := flowNodeMap[approvalRecord.NodeId]; ok {
			flowNodeMap[approvalRecord.NodeId] = append(tmpFlowNodeList, *approvalRecord)
		} else {
			tmpFlowNodeList := make([]contract.ContractApprovalRecord, 1)
			tmpFlowNodeList[0] = *approvalRecord
			flowNodeMap[approvalRecord.NodeId] = tmpFlowNodeList

			keySort = append(keySort, approvalRecord.NodeId)
		}

		// 待审批状态下，如果当前审批节点就是操作人，审批节点超过当前审批节点，且节点类型是抄送人，，那么标记为处理中
		if approvalItem.Status == "待审批" {
			if approvalRecord.ApproveUserId == sysUser.AdminId && approvalRecord.NodeId < approvalItem.CurrNodeId && approvalRecord.NodeType == "cc" {
				approvalItem.Status = "处理中"
			}
		}
	}

	// 作废权限
	if sysUser.AdminId == approvalItem.ApplyUserId && approvalItem.Status == "已审批" {
		opButton.Invalid = true
	}
	// 是否具有签回合同用印权限
	uploadStatus := []string{"已审批", "已签回"}
	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && strings.Contains(strings.Join(uploadStatus, ","), approvalItem.Status) {
		opButton.UploadFile = true
	}
	// 编辑权限
	editStatus := []string{"已驳回", "待提交", "已撤回"}
	if sysUser.AdminId == approvalItem.ApplyUserId && strings.Contains(strings.Join(editStatus, ","), approvalItem.Status) {
		opButton.Edit = true
	}

	return
}

// GetSealApprovalDetail 获取审批详情
func GetSealApprovalDetail(sealId int, sysUser *system.Admin) (sealMore *response.SealMoreResp, flowNodeListResp [][]contract.ContractApprovalRecord, opButton response.SealApprovalOpButton, err error) {
	sealInfo, err := seal.GetSealInfoById(sealId)
	if err != nil {
		err = errors.New(fmt.Sprint("获取用印详情失败,Err:"+err.Error(), err))
		return
	}
	sealAttachements, err := seal.GetAttachmentBySealId(sealId)
	if err != nil {
		err = errors.New(fmt.Sprint("获取用印附件失败,Err:"+err.Error(), err))
		return
	}
	fileUrls := make([]string, 0)
	if sealInfo.FileUrl != "" {
		fileUrls = append(fileUrls, sealInfo.FileUrl)
	}
	for _, v := range sealAttachements {
		fileUrls = append(fileUrls, v.FileUrl)
	}
	sealMore = &response.SealMoreResp{
		Seal:     sealInfo,
		FileUrls: fileUrls,
	}
	// 查询最近一次审批单信息
	lastApprovalInfo, err := contract.GetLastContractApprovalByContractId(sealInfo.SealId, "seal")
	if err != nil {
		if err.Error() != utils.ErrNoRow() {
			err = errors.New("获取最近一次审批单信息失败,ERR:" + err.Error())
		}
		err = nil
		return
	}
	if lastApprovalInfo != nil {
		// 获取审批操作和审批流数据
		tmpSealOpButton, tmpFlowNodeListResp, tmpErr := GetSealOpButton(sealInfo, lastApprovalInfo, sysUser)
		if tmpErr != nil {
			err = errors.New("获取用印按钮权限、审批流程失败，Err:" + tmpErr.Error())
			return
		}
		opButton = tmpSealOpButton
		flowNodeListResp = tmpFlowNodeListResp
	}

	return
}

// GetSealOpButton 获取用印审批操作权限
func GetSealOpButton(sealInfo *seal.Seal, contractApprovalInfo *contract.ContractApproval, opUser *system.Admin) (sealOpButton response.SealApprovalOpButton, flowNodeListResp [][]contract.ContractApprovalRecord, err error) {
	// 审批流
	approvalRecordList, err := contract.GetApprovalRecordListByApprovalId(contractApprovalInfo.ContractApprovalId)
	if err != nil {
		err = errors.New("获取审批失败，Err:" + err.Error())
		return
	}
	// 待审批状态下，如果是自己发起的审批单，同时已经经过了一轮审批，那么标记为处理中
	if contractApprovalInfo.Status == "待审批" {
		if contractApprovalInfo.ApplyUserId == opUser.AdminId && contractApprovalInfo.CurrNodeId > contractApprovalInfo.StartNodeId {
			sealInfo.Status = "处理中"
		}
	}
	flowNodeMap := make(map[int][]contract.ContractApprovalRecord, 0)
	keySort := make([]int, 0)

	for _, approvalRecord := range approvalRecordList {
		// 如果当前节点正好是该节点，同时审批单状态是待审批状态，然后当前账号又有权限，该账号也正是审批人，那么允许审批操作
		if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && contractApprovalInfo.Status == "待审批" {
			if opUser.AdminId == approvalRecord.ApproveUserId && approvalRecord.NodeType == "check" {
				sealOpButton.Approval = true
			}

			// 合规在审批过程中具有 部分修改权限
			if opUser.AdminId == approvalRecord.ApproveUserId && opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && approvalRecord.NodeType == "check" {
				sealOpButton.CheckEdit = true
			}
		}
		// 如果当前节点正好是该节点，同时审批单状态又是第一层节点
		if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && approvalRecord.PrevNodeId == 0 && contractApprovalInfo.Status == "待审批" {
			// 发起人具有撤回审批单权限
			if opUser.AdminId == sealInfo.UserId {
				sealOpButton.Cancel = true
			}
		}
		if tmpFlowNodeList, ok := flowNodeMap[approvalRecord.NodeId]; ok {
			flowNodeMap[approvalRecord.NodeId] = append(tmpFlowNodeList, *approvalRecord)
		} else {
			tmpFlowNodeList := make([]contract.ContractApprovalRecord, 1)
			tmpFlowNodeList[0] = *approvalRecord
			flowNodeMap[approvalRecord.NodeId] = tmpFlowNodeList

			keySort = append(keySort, approvalRecord.NodeId)
		}

		// 待审批状态下，如果当前审批节点就是操作人，审批节点超过当前审批节点，且节点类型是抄送人，，那么标记为处理中
		if contractApprovalInfo.Status == "待审批" {
			if approvalRecord.ApproveUserId == opUser.AdminId && approvalRecord.NodeId < contractApprovalInfo.CurrNodeId && approvalRecord.NodeType == "cc" {
				sealInfo.Status = "处理中"
			}
		}
	}
	for _, key := range keySort {
		flowNodeListResp = append(flowNodeListResp, flowNodeMap[key])
	}
	// 作废权限
	if opUser.AdminId == sealInfo.UserId && sealInfo.Status == "已审批" {
		sealOpButton.Invalid = true
	}
	// 是否具有签回合同用印权限
	uploadStatus := []string{"已审批", "已签回"}
	if opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && strings.Contains(strings.Join(uploadStatus, ","), sealInfo.Status) {
		sealOpButton.UploadFile = true
	}
	// 编辑权限
	editStatus := []string{"已驳回", "待提交", "已撤回"}
	if opUser.AdminId == sealInfo.UserId && strings.Contains(strings.Join(editStatus, ","), sealInfo.Status) {
		sealOpButton.Edit = true
	}
	return
}

// CancelSealApproval 撤回用印审批
func CancelSealApproval(sealId int, sysUser *system.Admin) (err error) {
	// 审批信息
	sealInfo, err := seal.GetSealInfoById(sealId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			err = errors.New("用印审批信息有误，Err：" + err.Error())
		}
		return
	}
	// 审批状态判断
	if sealInfo.Status != "待审批" {
		err = errors.New("用印状态异常，不允许撤回申请，当前用印状态：" + sealInfo.Status)
		return
	}
	// 操作人与申请人是否一致
	if sealInfo.UserId != sysUser.AdminId {
		err = errors.New("不允许撤回非本人提交的申请：" + strconv.Itoa(sealInfo.UserId))
		return
	}
	// 获取最近一次待审批的审批单信息
	approvalInfo, err := contract.GetLastContractApprovalByContractId(sealInfo.SealId, "seal")
	if err != nil {
		return
	}
	if approvalInfo.Status != "待审批" {
		err = errors.New("审批单状态异常，审批单状态：" + approvalInfo.Status)
		return
	}
	//获取当前审批单的审批流信息
	approvalRecordList, err := contract.GetContractApprovalRecordListByContractApprovalIdAndNodeId(approvalInfo.ContractApprovalId, approvalInfo.CurrNodeId)
	if err != nil {
		err = errors.New("获取审批流失败，Err:" + err.Error())
		return
	}
	if len(approvalRecordList) <= 0 {
		err = errors.New("找不到对应的审批流")
		return
	}
	for _, tmpApprovalRecord := range approvalRecordList {
		// 判断当前节点是否存在上级节点，如果存在，那么说明
		if tmpApprovalRecord.PrevNodeId > 0 {
			err = errors.New("合同已存在审批操作，不允许撤回申请")
			return
		}
	}
	// 获取当前审批单中所有待审批的流程流
	contractApprovalRecordList, err := contract.GetPendingContractApprovalRecordListByContractId(approvalInfo.ContractApprovalId, approvalInfo.CurrNodeId)
	if err != nil {
		return
	}
	// 撤回审批流
	err = approvalInfo.Cancel(approvalInfo, contractApprovalRecordList)
	if err != nil {
		return
	}
	// 添加操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, sysUser.AdminId, 0, "cancel", sysUser.RealName, "撤回申请", "")
	if err != nil {
		return
	}
	// 作废原有消息
	for _, contractApprovalRecord := range contractApprovalRecordList {
		go company.CancelCompanyApprovalMessage(contractApprovalRecord.ContractApprovalRecordId, 3)
	}

	return
}

// DelSealApproval 删除用印审批
func DelSealApproval(sealId int, sysUser *system.Admin) (err error) {
	// 审批信息
	sealInfo, err := seal.GetSealInfoById(sealId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			err = errors.New("用印审批信息有误，Err：" + err.Error())
		}
		return
	}
	// 审批状态判断
	if sealInfo.Status != "已撤回" {
		err = errors.New("用印状态异常，不允许删除，当前用印状态：" + sealInfo.Status)
		return
	}
	// 操作人与申请人是否一致
	if sealInfo.UserId != sysUser.AdminId {
		err = errors.New("不允许删除非本人提交的申请：" + strconv.Itoa(sealInfo.UserId))
		return
	}
	// 删除用印审批
	err = seal.DeleteSeal(sealInfo)
	if err != nil {
		err = errors.New("删除用印申请失败：" + strconv.Itoa(sealInfo.UserId))
		return
	}
	// 添加操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, sysUser.AdminId, 0, "del", sysUser.RealName, "删除申请", "")
	if err != nil {
		return
	}

	return
}

// InvalidSealApproval 作废用印审批
func InvalidSealApproval(sealId int, opUser *system.Admin) (err error) {
	//查询当前用印信息
	sealInfo, err := seal.GetSealInfoById(sealId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			err = errors.New(fmt.Sprint("根据用印编号:", sealId, " 找不到初始用印"))
		}
		return
	}
	if sealInfo.UserId != opUser.AdminId && opUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE {
		err = errors.New("当前账号无操作权限")
		return
	}
	if sealInfo.Status != "已审批" {
		err = errors.New("用印状态异常，不允许作废，当前用印状态：" + sealInfo.Status)
		return
	}

	//如果删除状态 >0，那么代表已经被删除了
	if sealInfo.IsDelete > 0 {
		err = errors.New("该用印已删除")
		return
	}

	//用印作废
	err = seal.Invalid(sealInfo)
	if err != nil {
		return
	}
	// 操作日志
	err = seal.AddSealOperationRecord(sealInfo.SealId, opUser.AdminId, 0, "invalid", opUser.RealName, "作废审批", "")
	if err != nil {
		return
	}

	//获取最近一次提交的审批单信息
	contractApproval, err := contract.GetLastContractApprovalByContractId(sealInfo.SealId, "seal")
	if err != nil {
		err = nil
		return
	}
	//如果有提测信息，那么需要给对应的审批人发送消息
	if contractApproval != nil {
		//作废后需要给审批者发送消息
		contractApprovalRecordList, tmpErr := contract.GetContractApprovalRecordListByContractApprovalId(contractApproval.ContractApprovalId)
		if tmpErr != nil {
			return
		}
		content := fmt.Sprint("作废", sealInfo.CompanyName, "用印申请")
		for _, contractApprovalRecord := range contractApprovalRecordList {
			if contractApprovalRecord.NodeType == "check" { //如果是审批人，那么需要发送消息给对方
				//操作人信息
				sysUserMobile := ""
				sysUser, _ := system.GetSysAdminById(contractApprovalRecord.ApproveUserId)
				if sysUser != nil {
					sysUserMobile = sysUser.Mobile
				}
				go services.AddCompanyApprovalMessage(opUser.AdminId, contractApprovalRecord.ApproveUserId, 0, contractApprovalRecord.ContractApprovalRecordId, 3, sourceType, 2, sealInfo.CompanyName, content, content, sysUserMobile)

			}
		}
	}

	return
}

// GetSealOperationRecordList 获取用印操作日志列表
func GetSealOperationRecordList(sealId int) (list []*seal.SealOperationRecordList, err error) {
	list, err = seal.GetSealOperationListBySealId(sealId)
	if len(list) > 0 {
		for k, item := range list {
			list[k].CreateTimeStr = item.CreateTime.Format(utils.FormatDateTime)
		}
	}
	return
}

// updateSealAndAttachment 更新用印申请，并更新附件
func updateSealAndAttachment(sealInfo *seal.Seal, updateCol []string, fileUrls []string) (err error) {
	o := orm.NewOrm()
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()
	err = sealInfo.Update(updateCol)
	if err != nil {
		return
	}
	now := time.Now()
	//删除原有的附件，新增最新的附件
	err = seal.DelAttachmentBySealId(sealInfo.SealId)
	if err != nil {
		return
	}
	attachments := make([]*seal.Attachment, 0)
	if len(fileUrls) > 1 {
		for _, v := range fileUrls {
			tmp := &seal.Attachment{
				SealId:     sealInfo.SealId,
				FileUrl:    v,
				ModifyTime: now,
				CreateTime: now,
			}
			attachments = append(attachments, tmp)
		}
		err = seal.AddAttachments(attachments)
	}
	return
}
