// ============================================================================
// This is auto-generated by gf cli tool only once. Fill this file as you wish.
// ============================================================================

package wf_flow_process

import (
	"github.com/gogf/gf/container/garray"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
)

type ProcessData struct {
	Id          int     `json:"id"`
	Mode        string  `json:"mode"`
	Name        string  `json:"name"`
	FlowId      uint    `json:"flow_id"`
	ProcessName string  `json:"process_name"`
	ProcessTo   string  `json:"process_to"`
	Style       string  `json:"style"`
	Process     *Entity `json:"process"`
}

//流程转出信息
type ProcessStepData struct {
	PrevId      int      `json:"prev_id"`
	Id          int      `json:"id"`
	ProcessName string   `json:"process_name"`
	ProcessType string   `json:"process_type"`
	Condition   []string `json:"condition"`
}

type SaveProcessReq struct {
	Id        int    `p:"id" v:"required#流程ID不能为空"`
	Left      string `p:"left" v:"required#流程坐标left不能为空"`
	Top       string `p:"top" v:"required#流程坐标top不能为空"`
	ProcessTo string `p:"process_to" `
}

type SaveProcessReqBatch struct {
	Data []*SaveProcessReq `p:"data" v:"required#数据不能为空"`
}

type SaveAttrReq struct {
	FlowId           int               `p:"flow_id" v:"required#工作流id不能为空"`
	ProcessId        int               `p:"process_id" v:required#流程id不能为空`
	ProcessName      string            `p:"process_name" v:required#流程名称不能为空`
	StyleWidth       string            `p:"style_width"`
	StyleHeight      string            `p:"style_height"`
	ProcessType      string            `p:"process_type"`
	WfAction         string            `p:"wf_action"`
	IsSing           string            `p:"is_sing"`
	IsBack           string            `p:"is_back"`
	AutoPerson       string            `p:"auto_person"`
	RangeUserIds     string            `p:"range_user_ids"`
	RangeUserText    string            `p:"range_user_text"`
	AutoSponsorIds   string            `p:"auto_sponsor_ids"`
	AutoSponsorText  string            `p:"auto_sponsor_text"`
	AutoRoleIds      string            `p:"auto_role_ids"`
	AutoRoleText     string            `p:"auto_role_text"`
	WorkText         string            `p:"work_text"`
	WorkIds          string            `p:"work_ids"`
	WfMode           string            `p:"wf_mode"`
	ProcessInSet     []ProcessInSetReq `p:"process_in_set"`
	WorkSql          string            `p:"work_sql"`
	WorkMsg          string            `p:"work_msg"`
	ProcessCondition string            `p:"process_condition"`
}

type ProcessInSetReq struct {
	Id        int      `p:"id"`
	Condition []string `p:"condition"`
}

//流程管理表字段信息
type FlowTableField struct {
	FieldName string `json:"field_name"`
	FieldText string `json:"field_text"`
}

type DeleteProcessReq struct {
	ProcessId int `p:"process_id" v:"required#流程ID不能为空" json:"process_id"`
	FlowId    int `p:"flow_id" v:"required#工作流Id不能为空" json:"flow_id"`
}

//获取流程下所有步骤信息
func ProcessAll(flowId int64) (total int64, processData []*ProcessData, err error) {
	var list []*Entity
	list, err = Model.Where("flow_id", flowId).Where("is_del", 0).Order("id asc").FindAll()
	if err != nil {
		g.Log().Error(err)
		err = gerror.New("获取流程数据失败")
		return
	}
	processData = make([]*ProcessData, len(list))
	for k, entity := range list {
		total += 1
		style := gjson.New(entity.Style)
		model := `<span style="color:red">未设置</span>`
		name := `<span style="color:red">未设置</span>`
		var work map[string]string
		if entity.AutoPerson == 3 {
			model = "办理人员"
			name = entity.RangeUserText
		}
		if entity.AutoPerson == 4 {
			model = "办理人员"
			name = entity.AutoSponsorText
		}
		if entity.AutoPerson == 5 {
			model = "办理角色"
			name = entity.AutoRoleText
		}
		if entity.AutoPerson == 6 {
			work = map[string]string{
				"1": "制单人员",
				"2": "制单人员领导",
			}
			model = `<span style="color:blue">事务处理</span>`
			name = work[entity.WorkIds]
		}
		nameAttr := ""
		if entity.ProcessType == "is_one" {
			nameAttr = `<span style="color:blue">[开始]</span>`
		} else {
			if entity.WfMode == 0 {
				nameAttr = "[直线]"
			} else if entity.WfMode == 1 {
				nameAttr = `<span style="color:lightgreen">[转出]</span>`
			} else {
				nameAttr = `<span style="color:red">[同步]</span>`
			}
		}
		heightUnit := "px"
		if style.GetString("height") == "auto" {
			heightUnit = ""
		}
		processData[k] = &ProcessData{
			Id:          entity.Id,
			Mode:        model,
			Name:        name,
			FlowId:      entity.FlowId,
			ProcessName: nameAttr + entity.ProcessName,
			ProcessTo:   entity.ProcessTo,
			Style: "width:" + style.GetString("width") + "px;height:" + style.GetString("height") +
				heightUnit + ";line-height:30px;color:#0e76a8;left:" + gconv.String(entity.Setleft) + "px;top:" + gconv.String(entity.Settop) + "px;",
			Process: entity,
		}
	}
	return
}

//保存流程步骤
func ProcessAdd(flowId int64) error {
	processList, err := Model.Order("id desc").FindAll("flow_id", flowId)
	if err != nil {
		g.Log().Error(err)
		return gerror.New("获取流程数据失败")
	}
	processCount := len(processList)
	processType := "is_step"
	var processSetLeft uint = 100
	var processSetTop uint = 100
	if processCount == 0 {
		processType = "is_one"
		processSetLeft = 100
		processSetTop = 100
	} else {
		//新建步骤显示在上一个步骤下方
		processType = "is_step"
		processSetLeft = processList[0].Setleft + 30
		processSetTop = processList[0].Settop + 30
	}

	style := gjson.New(nil)
	style.Set("width", "120")
	style.Set("height", "auto")
	style.Set("color", "#0e76a8")
	entity := &Entity{
		FlowId:      gconv.Uint(flowId),
		Setleft:     processSetLeft,
		Settop:      processSetTop,
		ProcessType: processType,
		Style:       style.MustToJsonString(),
		AutoPerson:  4,
		ProcessName: "步骤",
		IsSing:      1,
		IsBack:      1,
		WfAction:    "view",
	}
	_, err = Model.Save(entity)
	if err != nil {
		g.Log().Error(err)
		return gerror.New("保存流程步骤失败")
	}
	return nil
}

//保存设计
func SaveProcess(req *SaveProcessReqBatch) error {
	if req != nil && req.Data != nil {
		tx, err := g.DB().Begin()
		if err != nil {
			g.Log().Error(err)
			return gerror.New("保存失败")
		}
		entities := make([]*Entity, len(req.Data))
		for k, rq := range req.Data {
			entity, err := Model.FindOne(rq.Id)
			if err != nil || entity == nil {
				if err != nil {
					g.Log().Error(err)
				}
				tx.Rollback()
				return gerror.New("不存在的流程信息，请刷新重试。")
			}
			entity.Setleft = gconv.Uint(rq.Left)
			entity.Settop = gconv.Uint(rq.Top)
			entity.ProcessTo = rq.ProcessTo
			entities[k] = entity
		}
		_, err = Model.TX(tx).Data(entities).Save()
		if err != nil {
			g.Log().Error(err)
			tx.Rollback()
			return gerror.New("保存数据失败")
		}
		tx.Commit()
	}
	return nil
}

//获取流程管理表字段信息
func GetFlowTableFields(dbPrefix, database, tableName string) (fields []*FlowTableField, err error) {
	sql := "SELECT COLUMN_NAME as field_name,column_comment as field_text FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? " +
		"AND table_schema = ? "
	var result gdb.Result
	result, err = g.DB().GetAll(sql, dbPrefix+tableName, database)
	if err != nil {
		g.Log().Error(err)
		err = gerror.New("查询表字段数据失败")
	}
	result.Structs(&fields)
	return
}

//删除流程节点
func ProcessDelete(req *DeleteProcessReq) error {
	tx, err := g.DB().Begin()
	if err != nil {
		g.Log().Error(err)
		return gerror.New("开启处理事务失败")
	}
	_, err = Model.TX(tx).Delete(g.Map{
		Columns.Id:     req.ProcessId,
		Columns.FlowId: req.FlowId,
		Columns.IsDel:  0,
	})
	if err != nil {
		g.Log().Error(err)
		tx.Rollback()
		return gerror.New("删除失败")
	}
	list, err := Model.Where(Columns.FlowId, req.FlowId).Where(Columns.IsDel, 0).
		Where("FIND_IN_SET(?,process_to)", gconv.String(req.ProcessId)).FindAll()
	if err != nil {
		g.Log().Error(err)
		return gerror.New("获取节点连接失败")
	}
	if list != nil {
		for _, value := range list {
			s := gstr.Split(value.ProcessTo, ",")
			arr := garray.NewStrArrayFrom(s)
			key := arr.Search(gconv.String(req.ProcessId))
			arr.Remove(key)
			processTo := ""
			if arr.Len() > 0 {
				processTo = arr.Join(",")
			}
			value.Updatetime = gconv.Uint(gtime.Timestamp())
			value.ProcessTo = processTo
			_, err := Model.TX(tx).Save(value)
			if err != nil {
				g.Log().Error(err)
				tx.Rollback()
				return gerror.New("删除节点连线失败")
			}
		}
	}
	tx.Commit()
	return nil
}

//通过ID获取流程步骤信息
func GetProcessInfoById(id uint) (entity *Entity, err error) {
	entity, err = Model.FindOne(id)
	if err != nil {
		g.Log().Error(err)
		err = gerror.New("查询流程信息失败")
	}
	return
}

//查询流程信息
func GetProcessesByMap(where g.Map) (entities []*Entity, err error) {
	entities, err = Model.Where(where).FindAll()
	if err != nil {
		g.Log().Error(err)
		err = gerror.New("查询流程信息失败")
	}
	return
}

//通过ids获取多条流程步骤信息
func GetProcessInfosByIds(ids []uint) (entities []*Entity, err error) {
	entities, err = Model.Where("id in (?)", ids).FindAll()
	if err != nil {
		g.Log().Error(err)
		err = gerror.New("查询流程信息失败")
	}
	return
}
