package system

import (
	"github.com/beego/beego/v2/client/orm"
	"time"
)

//审批流程节点路线表
type ApprovalFlowNode struct {
	NodeId     int       `orm:"column(node_id);pk";json:"node_id"`         // 流程节点id
	FlowId     int       `orm:"column(flow_id);";json:"flow_id"`           // 流程id
	NodeName   string    `orm:"column(node_name);" json:"node_name"`       // 流程节点名称
	PrevNodeId int       `orm:"column(prev_node_id);" json:"prev_node_id"` //上级节点id,为0代表是开始节点
	NextNodeId int       `orm:"column(next_node_id);" json:"next_node_id"` //下级节点id,为0代表是结束节点
	NodeType   string    `orm:"column(node_type);" json:"node_type"`       //节点类型,审批人:check;抄送人:cc(Carbon Copy),默认是:check
	AuditType  int       `orm:"column(audit_type);" json:"audit_type"`     //多人审批时,1:或签(一名审批人同意即可),2:会签(需所有审批人同意)
	User       string    `orm:"column(user);" json:"user"`                 //所属用户,多个用英文,隔开;用户类型为user代表指定人id,manager代表几级主管,role代表角色类型
	Version    int       `orm:"column(version);" json:"version"`           // 所属流程版本
	CreateTime time.Time `orm:"column(create_time);" json:"create_time"`   // 创建时间
}

//审批列表数据
type ApprovalFlowNodeList struct {
	NodeId     int        `description:"流程节点id"`                                       // 流程节点id
	FlowId     int        `description:"流程id"`                                         // 流程id
	NodeName   string     `description:"流程节点名称"`                                       // 流程节点名称
	PrevNodeId int        `description:"上级节点id,为0代表是开始节点"`                             //上级节点id,为0代表是开始节点
	NextNodeId int        `description:"下级节点id,为0代表是结束节点"`                             //下级节点id,为0代表是结束节点
	NodeType   string     `description:"节点类型,审批人:check;抄送人:cc(Carbon Copy),默认是:check"` //节点类型,审批人:check;抄送人:cc(Carbon Copy),默认是:check
	AuditType  int        `description:"多人审批时,1:或签(一名审批人同意即可),2:会签(需所有审批人同意)"`         //多人审批时,1:或签(一名审批人同意即可),2:会签(需所有审批人同意)
	User       string     `description:"用户列表"`                                         //所属用户,多个用英文,隔开;用户类型为user代表指定人id,manager代表几级主管,role代表角色类型
	UserArr    []NodeUser `json:"User";description:"节点用户"`                             //所属用户,多个用英文,隔开;用户类型为user代表指定人id,manager代表几级主管,role代表角色类型
	Version    int        `description:"所属流程版本"`                                       // 所属流程版本
	CreateTime time.Time  `description:"创建时间"`                                         // 创建时间
	UserList   []User     `description:"审批人、抄送人列表信息"`                                  // 审批人、抄送人列表信息
}

//审批人、抄送人信息
type User struct {
	AdminId      int    `description:"人员id(审批人、抄送人)"`
	RoleId       int    `description:"人员角色id(审批人、抄送人)"`
	Name         string `description:"人员名称(审批人、抄送人)"`
	RoleName     string `description:"人员角色名称(审批人、抄送人)"`
	RoleTypeCode string `description:"人员角色类型(审批人、抄送人)"`
	Mobile       string `description:"手机号(审批人、抄送人)"`
}

//根据流程id获取整个审批流程节点路线
func GetListByFlowId(flowId, version int) (items []*ApprovalFlowNodeList, err error) {
	sql := `SELECT * FROM approval_flow_node WHERE flow_id=? AND version=? order by node_id asc `
	o := orm.NewOrm()
	_, err = o.Raw(sql, flowId, version).QueryRows(&items)
	return
}

//根据节点id获取节点信息
func GetByNodeId(nodeId int) (item *ApprovalFlowNode, err error) {
	sql := `SELECT * FROM approval_flow_node WHERE node_id=? LIMIT 1 `
	o := orm.NewOrm()
	err = o.Raw(sql, nodeId).QueryRow(&item)
	return
}

//更新审批流
func UpdateFlow(flowId int, flowNodeList []*ApprovalFlowNode) (err error) {
	o := orm.NewOrm()
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()
	var item ApprovalFlow
	sql := `SELECT * FROM approval_flow WHERE flow_id=? FOR UPDATE `

	err = to.Raw(sql, flowId).QueryRow(&item)
	if err != nil {
		return
	}
	//新版本号
	newVer := item.CurrVersion + 1
	item.CurrVersion = newVer
	_, err = to.Update(&item, "CurrVersion")
	if err != nil {
		return
	}

	//新增节点
	prevNodeId := 0
	for _, node := range flowNodeList {
		node.Version = newVer
		node.PrevNodeId = prevNodeId //上级节点

		nodeId, tmpErr := to.Insert(node)
		if tmpErr != nil {
			err = tmpErr
			return
		}

		//记录节点id
		node.NodeId = int(nodeId)
		//上一级节点id
		prevNodeId = int(nodeId)
	}

	//修改对应节点的下级节点
	nextNodeId := 0
	lenNodeList := len(flowNodeList) - 1
	for i := lenNodeList; i >= 0; i-- {
		node := flowNodeList[i]
		node.NextNodeId = nextNodeId
		_, tmpErr := to.Update(node, "NextNodeId")
		if tmpErr != nil {
			err = tmpErr
			return
		}
		nextNodeId = node.NodeId
	}

	return
}