package sandbox

import (
	"encoding/json"
	"eta/eta_api/models"
	"eta/eta_api/models/company"
	"eta/eta_api/models/sandbox"
	"eta/eta_api/models/sandbox/request"
	"eta/eta_api/models/system"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/utils"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// AddSandbox 新增沙盘
//func AddSandbox(req request.AddAndEditSandbox, opUserId int, opUserName string, ignoreVariety bool) (resp *sandbox.SandboxSaveResp, err error) {
//	resp = new(sandbox.SandboxSaveResp)
//	// 获取产品权限详情
//	var permissionName string
//	if !ignoreVariety {
//		chartPermissionInfo, e := company.GetChartPermissionListById(req.ChartPermissionId)
//		if e != nil {
//			err = e
//			return
//		}
//		permissionName = chartPermissionInfo.PermissionName
//	}
//	//沙盘主表信息
//	sandboxInfo := &sandbox.Sandbox{
//		Name:                utils.TrimStr(req.Name),
//		ChartPermissionId:   req.ChartPermissionId,
//		ChartPermissionName: permissionName,
//		CurrVersion:         1,
//		Code:                GenerateCode(),
//		Content:             req.Content,
//		PicUrl:              utils.TrimStr(req.PicUrl),
//		OpUserId:            opUserId,
//		OpUserName:          opUserName,
//		IsDelete:            0,
//		ModifyTime:          time.Now(),
//		CreateTime:          time.Now(),
//	}
//	//沙盘版本表信息
//	sandboxVersionInfo := &sandbox.SandboxVersion{
//		Name:                sandboxInfo.Name,
//		ChartPermissionId:   sandboxInfo.ChartPermissionId,
//		ChartPermissionName: sandboxInfo.ChartPermissionName,
//		CurrVersion:         sandboxInfo.CurrVersion,
//		Content:             sandboxInfo.Content,
//		PicUrl:              sandboxInfo.PicUrl,
//		OpUserId:            sandboxInfo.OpUserId,
//		OpUserName:          sandboxInfo.OpUserName,
//		VersionCode:         GenerateVersionCode(sandboxInfo.SandboxId, sandboxInfo.CurrVersion),
//		IsDelete:            sandboxInfo.IsDelete,
//		CreateTime:          sandboxInfo.CreateTime,
//	}
//	//沙盘草稿表信息
//	sandboxDraftInfo := &sandbox.SandboxDraft{
//		Name:                sandboxInfo.Name,
//		ChartPermissionId:   sandboxInfo.ChartPermissionId,
//		ChartPermissionName: sandboxInfo.ChartPermissionName,
//		CurrVersion:         sandboxInfo.CurrVersion,
//		Content:             sandboxInfo.Content,
//		OpUserId:            sandboxInfo.OpUserId,
//		OpUserName:          sandboxInfo.OpUserName,
//		CreateTime:          sandboxInfo.CreateTime,
//	}
//
//	//新增沙盘
//	err = sandbox.AddNewSandbox(sandboxInfo, sandboxVersionInfo, sandboxDraftInfo)
//	if err != nil {
//		return
//	}
//	resp.Sandbox = sandboxInfo
//	resp.VersionCode = sandboxVersionInfo.VersionCode
//	return
//}

// UpdateSandbox 更新沙盘
//func UpdateSandbox(req request.AddAndEditSandbox, opUserId int, opUserName string, ignoreVariety bool) (resp *sandbox.SandboxSaveResp, err error, errMsg string) {
//	resp = new(sandbox.SandboxSaveResp)
//	// 获取沙盘版本信息
//	sandboxVersion, err := sandbox.GetSandboxVersionBySandboxVersionCode(req.SandboxVersionCode)
//	if err != nil {
//		if err.Error() == utils.ErrNoRow() {
//			errMsg = "找不到该版本"
//			err = errors.New(errMsg)
//		}
//		return
//	}
//	// 获取沙盘主表信息
//	sandboxInfo, err := sandbox.GetSandboxById(sandboxVersion.SandboxId)
//	if err != nil {
//		if err.Error() == utils.ErrNoRow() {
//			errMsg = "找不到该沙盘"
//			err = errors.New(errMsg)
//		}
//		return
//	}
//	//沙盘名称是否更改校验
//	var isUpdateName, isUpdateContent bool
//	if sandboxInfo.Name != utils.TrimStr(req.Name) {
//		isUpdateName = true
//	}
//
//	// 沙盘内容md5比对,不一致则代表有做更改
//	//if utils.MD5(sandboxInfo.Content) != utils.MD5(req.Content) {
//	//	isUpdateContent = true
//	//}
//	if checkoutContent(sandboxInfo.Content, req.Content) {
//		isUpdateContent = true
//	}
//
//	//如果沙盘名称和沙盘内容都没有做过修改,那么就不做保存
//	if isUpdateName == false && isUpdateContent == false {
//		return
//	}
//
//	// 获取产品权限详情
//	var permissionName string
//	if !ignoreVariety {
//		chartPermissionInfo, e := company.GetChartPermissionListById(req.ChartPermissionId)
//		if e != nil {
//			err = e
//			return
//		}
//		permissionName = chartPermissionInfo.PermissionName
//	}
//
//	//如果只更新了沙盘名称,那么只去修改最新版本的沙盘名称,而不去累计版本
//	if isUpdateName == true && isUpdateContent == false {
//		sandboxInfo.Name = utils.TrimStr(req.Name)
//		sandboxInfo.ChartPermissionId = req.ChartPermissionId
//		sandboxInfo.ChartPermissionName = permissionName
//		sandboxInfo.Content = req.Content
//		sandboxInfo.PicUrl = utils.TrimStr(req.PicUrl)
//		sandboxInfo.OpUserId = opUserId
//		sandboxInfo.OpUserName = opUserName
//		sandboxInfo.ModifyTime = time.Now()
//		var updateSandboxColumn = []string{"Name", "ChartPermissionId", "ChartPermissionName", "PicUrl", "OpUserId", "OpUserName", "ModifyTime"}
//
//		//沙盘版本表信息
//		sandboxVersionInfo, tmpErr := sandbox.GetSandboxVersionBySandbox2VersionId(sandboxInfo.SandboxId, sandboxInfo.CurrVersion)
//		if tmpErr != nil {
//			err = tmpErr
//			return
//		}
//		sandboxVersionInfo.Name = sandboxInfo.Name
//		sandboxVersionInfo.ChartPermissionId = sandboxInfo.ChartPermissionId
//		sandboxVersionInfo.ChartPermissionName = sandboxInfo.ChartPermissionName
//		sandboxVersionInfo.PicUrl = sandboxInfo.PicUrl
//		sandboxVersionInfo.OpUserId = sandboxInfo.OpUserId
//		sandboxVersionInfo.OpUserName = sandboxInfo.OpUserName
//		var updateSandboxVersionColumn = []string{"Name", "ChartPermissionId", "ChartPermissionName", "PicUrl", "OpUserId", "OpUserName"}
//
//		//沙盘草稿表信息
//		sandboxDraftInfo := &sandbox.SandboxDraft{
//			Name:                sandboxInfo.Name,
//			ChartPermissionId:   sandboxInfo.ChartPermissionId,
//			ChartPermissionName: sandboxInfo.ChartPermissionName,
//			CurrVersion:         sandboxInfo.CurrVersion,
//			Content:             sandboxInfo.Content,
//			OpUserId:            sandboxInfo.OpUserId,
//			OpUserName:          sandboxInfo.OpUserName,
//			CreateTime:          time.Now(),
//		}
//
//		//修改沙盘
//		err = sandbox.UpdateSandboxName(sandboxInfo, sandboxVersionInfo, sandboxDraftInfo, updateSandboxColumn, updateSandboxVersionColumn)
//		if err != nil {
//			return
//		}
//		resp.Sandbox = sandboxInfo
//		resp.VersionCode = sandboxVersionInfo.VersionCode
//	} else {
//		sandboxInfo.Name = utils.TrimStr(req.Name)
//		sandboxInfo.ChartPermissionId = req.ChartPermissionId
//		sandboxInfo.ChartPermissionName = permissionName
//		sandboxInfo.CurrVersion = sandboxInfo.CurrVersion + 1
//		sandboxInfo.Content = req.Content
//		sandboxInfo.PicUrl = utils.TrimStr(req.PicUrl)
//		sandboxInfo.OpUserId = opUserId
//		sandboxInfo.OpUserName = opUserName
//		sandboxInfo.ModifyTime = time.Now()
//
//		var updateSandbox = []string{"Name", "ChartPermissionId", "ChartPermissionName", "CurrVersion", "Content", "PicUrl", "OpUserId", "OpUserName", "ModifyTime"}
//
//		//沙盘版本表信息
//		sandboxVersionInfo := &sandbox.SandboxVersion{
//			Name:                sandboxInfo.Name,
//			ChartPermissionId:   sandboxInfo.ChartPermissionId,
//			ChartPermissionName: sandboxInfo.ChartPermissionName,
//			CurrVersion:         sandboxInfo.CurrVersion,
//			Content:             sandboxInfo.Content,
//			SvgData:             req.SvgData,
//			PicUrl:              sandboxInfo.PicUrl,
//			OpUserId:            sandboxInfo.OpUserId,
//			OpUserName:          sandboxInfo.OpUserName,
//			VersionCode:         GenerateVersionCode(sandboxInfo.SandboxId, sandboxInfo.CurrVersion),
//			IsDelete:            sandboxInfo.IsDelete,
//			CreateTime:          time.Now(),
//		}
//		//沙盘草稿表信息
//		sandboxDraftInfo := &sandbox.SandboxDraft{
//			Name:                sandboxInfo.Name,
//			ChartPermissionId:   sandboxInfo.ChartPermissionId,
//			ChartPermissionName: sandboxInfo.ChartPermissionName,
//			CurrVersion:         sandboxInfo.CurrVersion,
//			Content:             sandboxInfo.Content,
//			OpUserId:            sandboxInfo.OpUserId,
//			OpUserName:          sandboxInfo.OpUserName,
//			CreateTime:          time.Now(),
//		}
//
//		//修改沙盘
//		err = sandbox.UpdateSandbox(sandboxInfo, updateSandbox, sandboxVersionInfo, sandboxDraftInfo)
//		if err != nil {
//			return
//		}
//		resp.Sandbox = sandboxInfo
//		resp.VersionCode = sandboxVersionInfo.VersionCode
//	}
//	return
//}

// AddSandboxDraft 新增沙盘草稿
func AddSandboxDraft(sandboxId int, req request.AddAndEditSandbox, opUserId int, opUserName string) (sandboxDraftInfo *sandbox.SandboxDraft, err error) {
	//获取最近一条草稿箱的数据
	lastSandboxDraft, err := sandbox.GetLastSandboxDraftById(sandboxId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		return
	}
	//如果最近一条沙盘草稿数据不为空的话,那么需要校验下最近一次的图表数据是否与提交的这次一致
	if lastSandboxDraft != nil {
		//沙盘名称是否更改校验
		var isUpdateName, isUpdateContent bool
		if lastSandboxDraft.Name != utils.TrimStr(req.Name) {
			isUpdateName = true
		}

		// 沙盘内容md5比对,不一致则代表有做更改
		//if utils.MD5(lastSandboxDraft.Content) != utils.MD5(req.Content) {
		//	isUpdateContent = true
		//}
		if checkoutContent(lastSandboxDraft.Content, req.Content) {
			isUpdateContent = true
		}

		//如果沙盘名称和沙盘内容都没有做过修改,那么就不做保存
		if isUpdateName == false && isUpdateContent == false {
			return
		}
	}
	// 获取产品权限详情
	chartPermissionInfo, err := company.GetChartPermissionListById(req.ChartPermissionId)
	if err != nil {
		return
	}
	//沙盘草稿表信息
	sandboxDraftInfo = &sandbox.SandboxDraft{
		SandboxId:           sandboxId,
		Name:                utils.TrimStr(req.Name),
		ChartPermissionId:   req.ChartPermissionId,
		ChartPermissionName: chartPermissionInfo.PermissionName,
		Content:             req.Content,
		OpUserId:            opUserId,
		OpUserName:          opUserName,
		CreateTime:          time.Now(),
	}

	//新增沙盘草稿
	err = sandbox.AddSandboxDraft(sandboxDraftInfo)
	return
}

// UpdateSandboxEditMark 更新沙盘当前更新状态
// status 枚举值 1:编辑中,0:完成编辑, 2:只做查询
func UpdateSandboxEditMark(sandboxId, nowUserId, status int, nowUserName string) (ret models.MarkReportResp, err error) {
	//更新标记key
	key := fmt.Sprint(`crm:sandbox:edit:`, sandboxId)
	opUserId, e := utils.Rc.RedisInt(key)
	var opUser models.MarkReportItem
	if e != nil {
		opUserInfoStr, tErr := utils.Rc.RedisString(key)
		if tErr == nil {
			tErr = json.Unmarshal([]byte(opUserInfoStr), &opUser)
			if tErr == nil {
				opUserId = opUser.AdminId
			}
		}
	}
	if opUserId > 0 && opUserId != nowUserId {
		editor := opUser.Editor
		if editor == "" {
			//查询账号的用户姓名
			otherInfo, e := system.GetSysAdminById(opUserId)
			if e != nil {
				err = fmt.Errorf("查询其他编辑者信息失败")
				return
			}
			editor = otherInfo.RealName
		}

		ret.Status = 1
		ret.Msg = fmt.Sprintf("当前%s正在编辑中", editor)
		ret.Editor = editor
		return
	}
	if status == 1 {
		nowUser := &models.MarkReportItem{AdminId: nowUserId, Editor: nowUserName}
		bt, e := json.Marshal(nowUser)
		if e != nil {
			err = fmt.Errorf("格式化编辑者信息失败")
			return
		}
		if opUserId > 0 {
			utils.Rc.Do("SETEX", key, int64(300), string(bt)) //3分钟缓存
		} else {
			utils.Rc.SetNX(key, string(bt), time.Second*60*5) //3分钟缓存
		}
	} else if status == 0 {
		//清除编辑缓存
		_ = utils.Rc.Delete(key)
	}
	return
}

// ResetDraftToLastVersion  重置沙盘草稿至最新版本
//func ResetDraftToLastVersion(sandboxId, opUserId int, opUserName string) (sandboxDraftInfo *sandbox.SandboxDraft, err error) {
//	// 获取沙盘主表信息
//	sandboxInfo, err := sandbox.GetSandboxById(sandboxId)
//	if err != nil {
//		return
//	}
//
//	//沙盘草稿表信息
//	sandboxDraftInfo = &sandbox.SandboxDraft{
//		SandboxId:           sandboxInfo.SandboxId,
//		Name:                sandboxInfo.Name,
//		ChartPermissionId:   sandboxInfo.ChartPermissionId,
//		ChartPermissionName: sandboxInfo.ChartPermissionName,
//		Content:             sandboxInfo.Content,
//		OpUserId:            opUserId,
//		OpUserName:          opUserName,
//		CreateTime:          time.Now(),
//	}
//
//	//新增沙盘草稿
//	err = sandbox.AddSandboxDraft(sandboxDraftInfo)
//	return
//}

// DeleteSandbox 删除沙盘
func DeleteSandbox(sandboxId int) (err error) {
	// 获取沙盘主表信息
	sandboxInfo, err := sandbox.GetSandboxById(sandboxId)
	if err != nil {
		return
	}

	sandboxInfo.IsDelete = 1
	var updateSandboxColumn = []string{"IsDelete"}
	err = sandboxInfo.Update(updateSandboxColumn)
	return
}

// DeleteSandboxVersion 删除沙盘版本
//func DeleteSandboxVersion(sandboxVersionCode string, opUserId int) (err error, errMsg string) {
//	// 获取沙盘版本信息
//	sandboxVersion, err := sandbox.GetSandboxVersionBySandboxVersionCode(sandboxVersionCode)
//	if err != nil {
//		if err.Error() == utils.ErrNoRow() {
//			errMsg = "找不到该版本"
//			err = errors.New(errMsg)
//		}
//		return
//	}
//
//	/*key := fmt.Sprint(`crm:sandbox:edit:`, sandboxVersion.SandboxId)
//	nowOpUserId, _ := utils.Rc.RedisInt(key)
//	//如果当前有人操作,且获取当前操作人不是本人,那么不允许删除
//	if nowOpUserId > 0 && nowOpUserId != opUserId {
//		errMsg = "当前有其他人正在编辑,不允许删除该沙盘"
//		err = errors.New(errMsg)
//		return
//	}*/
//
//	markStatus, err := UpdateSandboxEditMark(sandboxVersion.SandboxId, opUserId, 2, "")
//	if err != nil {
//		errMsg = "查询标记状态失败"
//		err = errors.New("查询标记状态失败,Err:" + err.Error())
//		return
//	}
//	if markStatus.Status == 1 {
//		errMsg = fmt.Sprintf("当前%s正在编辑,不允许删除该沙盘", markStatus.Editor)
//		err = errors.New(errMsg)
//		return
//	}
//
//	// 获取沙盘主表信息
//	sandboxInfo, err := sandbox.GetSandboxById(sandboxVersion.SandboxId)
//	if err != nil {
//		return
//	}
//
//	// 删除最新版本,需要将上一个版本的给找出来覆盖
//	if sandboxVersion.CurrVersion == sandboxInfo.CurrVersion {
//		lastSandboxVersion, tmpErr := sandbox.GetLastSandboxVersionBySandbox2VersionId(sandboxInfo.SandboxId, sandboxVersion.CurrVersion)
//		if tmpErr != nil {
//			// 如果找不到,说明是删除整个沙盘,不仅仅是某个版本
//			if tmpErr.Error() == utils.ErrNoRow() {
//				sandboxInfo.IsDelete = 1
//				var updateSandboxColumn = []string{"IsDelete"}
//				err = sandboxInfo.Update(updateSandboxColumn)
//				return
//			}
//			err = tmpErr
//			return
//		} else {
//			//将当前沙盘信息修复到上一个版本
//			sandboxInfo.Content = lastSandboxVersion.Content
//			sandboxInfo.CurrVersion = lastSandboxVersion.CurrVersion
//			sandboxInfo.PicUrl = lastSandboxVersion.PicUrl
//			err = sandboxInfo.Update([]string{"Content", "CurrVersion", "PicUrl"})
//			if err != nil {
//				return
//			}
//		}
//	}
//	//将原来的版本标记删除
//	sandboxVersion.IsDelete = 1
//	err = sandboxVersion.Update([]string{"IsDelete"})
//
//	return
//}

// GetSandboxVersionDetailByCode 获取沙盘的版本数据
func GetSandboxVersionDetailByCode(sandboxVersionCode string) (sandboxVersionInfo *sandbox.SandboxVersion, err error) {
	// 获取沙盘版本信息
	sandboxVersionInfo, err = sandbox.GetSandboxVersionBySandboxVersionCode(sandboxVersionCode)
	return
}

// GetLastSandboxInfo 获取最后一次操作的沙盘数据
func GetLastSandboxInfo(sandboxId int) (sandboxInfo *sandbox.Sandbox, err error) {
	// 获取沙盘主表信息
	sandboxInfo, err = sandbox.GetSandboxById(sandboxId)
	return
	//if err != nil {
	//	return
	//}
	//
	////获取最近一条草稿箱的数据(写到一半没有保存,然后退出去了)
	//lastSandboxDraft, err := sandbox.GetLastSandboxDraftById(sandboxId)
	//if err != nil && err.Error() != utils.ErrNoRow() {
	//	return
	//}
	////如果最近一条沙盘草稿数据不为空的话,那么需要校验下最近一次的图表数据是否与提交的这次一致
	//if lastSandboxDraft != nil {
	//	sandboxInfo = &sandbox.Sandbox{
	//		SandboxId:           sandboxId,
	//		Name:                lastSandboxDraft.Name,
	//		ChartPermissionId:   lastSandboxDraft.ChartPermissionId,
	//		ChartPermissionName: lastSandboxDraft.ChartPermissionName,
	//		CurrVersion:         lastSandboxDraft.CurrVersion,
	//		Content:             lastSandboxDraft.Content,
	//		OpUserId:            lastSandboxDraft.OpUserId,
	//		OpUserName:          lastSandboxDraft.OpUserName,
	//		IsDelete:            0,
	//		ModifyTime:          lastSandboxDraft.CreateTime,
	//		CreateTime:          lastSandboxDraft.CreateTime,
	//	}
	//}
	return
}

// GenerateCode 生成沙盘code
func GenerateCode() string {
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	return utils.MD5(fmt.Sprint("sandbox_") + timestamp)
}

// GenerateVersionCode 生成沙盘版本code
func GenerateVersionCode(sandboxId, sandboxVersion int) string {
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	return utils.MD5(fmt.Sprint("sandbox_version_", sandboxId, "_", sandboxVersion) + timestamp)
}

// ContentStruct 沙盘内容结构体
type ContentStruct struct {
	Cells []struct {
		Attrs struct {
			Line struct {
				SourceMarker    bool   `json:"sourceMarker"`
				Stroke          string `json:"stroke"`
				StrokeDasharray string `json:"strokeDasharray"`
			} `json:"line"`
			Rect struct {
				Fill            string      `json:"fill"`
				Stroke          string      `json:"stroke"`
				StrokeDasharray interface{} `json:"strokeDasharray"`
				StrokeWidth     int64       `json:"strokeWidth"`
			} `json:"rect"`
			Text struct {
				Fill       string  `json:"fill"`
				FontSize   float64 `json:"fontSize"`
				FontWeight string  `json:"fontWeight"`
				LineHeight float64 `json:"lineHeight"`
				Text       string  `json:"text"`
				TextWrap   struct {
					Text  string `json:"text"`
					Width int64  `json:"width"`
				} `json:"textWrap"`
			} `json:"text"`
		} `json:"attrs"`
		Data struct {
			Key string `json:"key"`
		} `json:"data"`
		ID    string `json:"id"`
		Ports struct {
			Groups struct {
				Port_bottom struct {
					Attrs struct {
						Circle struct {
							Fill        string `json:"fill"`
							Magnet      bool   `json:"magnet"`
							R           int64  `json:"r"`
							Stroke      string `json:"stroke"`
							StrokeWidth int64  `json:"strokeWidth"`
						} `json:"circle"`
					} `json:"attrs"`
					Position string `json:"position"`
					ZIndex   int64  `json:"zIndex"`
				} `json:"port-bottom"`
				Port_left struct {
					Attrs struct {
						Circle struct {
							Fill        string `json:"fill"`
							Magnet      bool   `json:"magnet"`
							R           int64  `json:"r"`
							Stroke      string `json:"stroke"`
							StrokeWidth int64  `json:"strokeWidth"`
						} `json:"circle"`
					} `json:"attrs"`
					Position string `json:"position"`
					ZIndex   int64  `json:"zIndex"`
				} `json:"port-left"`
				Port_right struct {
					Attrs struct {
						Circle struct {
							Fill        string `json:"fill"`
							Magnet      bool   `json:"magnet"`
							R           int64  `json:"r"`
							Stroke      string `json:"stroke"`
							StrokeWidth int64  `json:"strokeWidth"`
						} `json:"circle"`
					} `json:"attrs"`
					Position string `json:"position"`
					ZIndex   int64  `json:"zIndex"`
				} `json:"port-right"`
				Port_top struct {
					Attrs struct {
						Circle struct {
							Fill        string `json:"fill"`
							Magnet      bool   `json:"magnet"`
							R           int64  `json:"r"`
							Stroke      string `json:"stroke"`
							StrokeWidth int64  `json:"strokeWidth"`
						} `json:"circle"`
					} `json:"attrs"`
					Position string `json:"position"`
					ZIndex   int64  `json:"zIndex"`
				} `json:"port-top"`
			} `json:"groups"`
			Items []struct {
				Group string `json:"group"`
				ID    string `json:"id"`
			} `json:"items"`
		} `json:"ports"`
		Position struct {
			X float64 `json:"x"`
			Y float64 `json:"y"`
		} `json:"position"`
		Shape string `json:"shape"`
		Size  struct {
			Height float64 `json:"height"`
			Width  float64 `json:"width"`
		} `json:"size"`
		Source struct {
			Cell string `json:"cell"`
			Port string `json:"port"`
		} `json:"source"`
		Target struct {
			Cell string `json:"cell"`
			Port string `json:"port"`
		} `json:"target"`
		ZIndex int64 `json:"zIndex"`
	} `json:"cells"`
}

type SendBoxNodeData struct {
	linkData []SandBoxLinkData `json:"linkData"`
	linkFold bool              `json:"linkFold"`
}

type SandBoxLinkData struct {
	RId          string              `json:"RId"`
	Id           int                 `json:"Id"`
	Name         string              `json:"Name"`
	Type         int                 `json:"Type"`
	Editing      bool                `json:"editing"`
	DatabaseType int                 `json:"databaseType"`
	DetailParams SandBoxDetailParams `json:"detailParams"`
}

type SandBoxDetailParams struct {
	Code       string `json:"code"`
	Id         int    `json:"id"`
	ClassifyId int    `json:"classifyId"`
}

// checkoutContent 校验内容是否变更
func checkoutContent(oldContent, reqContent string) (isUpdate bool) {
	defer func() {
		// 沙盘内容md5比对,不一致则代表有做更改
		if utils.MD5(oldContent) != utils.MD5(reqContent) {
			isUpdate = true
		}
	}()
	var oldContentInfo, reqContentInfo ContentStruct
	err := json.Unmarshal([]byte(oldContent), &oldContentInfo)
	if err != nil {
		fmt.Println("old json.Unmarshal err:", err)
		return
	}
	oldContentInfoByte, err := json.Marshal(oldContentInfo)
	if err != nil {
		fmt.Println("old json.Marshal err:", err)
		return
	}
	oldContent = string(oldContentInfoByte)

	err = json.Unmarshal([]byte(reqContent), &reqContentInfo)
	if err != nil {
		fmt.Println("req json.Unmarshal err:", err)
		return
	}
	reqContentInfoByte, err := json.Marshal(reqContentInfo)
	if err != nil {
		fmt.Println("req json.Marshal err:", err)
		return
	}
	reqContent = string(reqContentInfoByte)

	return
}

func sandboxClassifyHaveChild(allNode []*sandbox.SandboxClassifyItems, node *sandbox.SandboxClassifyItems) (childs []*sandbox.SandboxClassifyItems, yes bool) {
	for _, v := range allNode {
		if v.ParentId == node.SandboxClassifyId {
			childs = append(childs, v)
		}
	}
	if len(childs) > 0 {
		yes = true
	}
	return
}

func SandboxClassifyItemsMakeTree(sysUser *system.Admin, allNode []*sandbox.SandboxClassifyItems, node *sandbox.SandboxClassifyItems) {

	childs, _ := sandboxClassifyHaveChild(allNode, node) //判断节点是否有子节点并返回
	if len(childs) > 0 {

		node.Children = append(node.Children, childs[0:]...) //添加子节点
		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
			_, has := sandboxClassifyHaveChild(allNode, v)
			if has {
				SandboxClassifyItemsMakeTree(sysUser, allNode, v) //递归添加节点
			} else {
				childrenArr := make([]*sandbox.SandboxClassifyItems, 0)
				v.Children = childrenArr
			}
		}
	} else {
		childrenArr := make([]*sandbox.SandboxClassifyItems, 0)
		node.Children = childrenArr
	}
}

// GetSandboxClassifyListForMe 获取我创建的沙盘
func GetSandboxClassifyListForMe(adminInfo system.Admin, resp *sandbox.SandboxClassifyListResp, sandboxClassifyId int) (errMsg string, err error) {
	rootList, err := sandbox.GetSandboxClassifyByParentId(sandboxClassifyId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		errMsg = "获取失败"
		return
	}

	classifyAll, err := sandbox.GetSandboxClassifyByParentId(sandboxClassifyId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		errMsg = "获取失败"
		return
	}

	sandboxAll, err := sandbox.GetSandboxInfoByAdminId(adminInfo.AdminId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		errMsg = "获取失败"
		return
	}

	sandListMap := make(map[int][]*sandbox.SandboxClassifyItems)
	for _, v := range sandboxAll {
		if _, ok := sandListMap[v.SandboxClassifyId]; !ok {
			list := make([]*sandbox.SandboxClassifyItems, 0)
			list = append(list, v)
			sandListMap[v.SandboxClassifyId] = list
		} else {
			sandListMap[v.SandboxClassifyId] = append(sandListMap[v.SandboxClassifyId], v)
		}
	}

	nodeAll := make([]*sandbox.SandboxClassifyItems, 0)
	for k := range rootList {
		rootNode := rootList[k]
		SandboxClassifyItemsMakeTree(&adminInfo, classifyAll, rootNode)
		nodeAll = append(nodeAll, rootNode)
	}
	//for k := range nodeAll {
	//
	//}
	newAll := SandboxItemsMakeTree(nodeAll, sandListMap, sandboxClassifyId)
	resp.AllNodes = newAll

	return
}

// HandleNoPermissionSandbox 图表列表返回,将没有权限的图表移除
func HandleNoPermissionSandbox(allNodes []*sandbox.SandboxClassifyItems, noPermissionChartIdMap map[int]bool) (newAllNodes []*sandbox.SandboxClassifyItems) {
	// 移除没有权限的图表
	newAllNodes = make([]*sandbox.SandboxClassifyItems, 0)
	for _, node := range allNodes {
		// 二级分类
		tmpNodeInfo := *node
		tmpNodeList := make([]*sandbox.SandboxClassifyItems, 0)
		if node.Children != nil {
			for _, chartList := range node.Children {
				tmpInfo := *chartList
				tmpList := make([]*sandbox.SandboxClassifyItems, 0)

				if chartList.Children != nil {
					for _, chartInfo := range chartList.Children {
						thirdInfo := *chartInfo
						thirdList := make([]*sandbox.SandboxClassifyItems, 0)
						// 如果指标不可见,那么就不返回该指标
						if _, ok := noPermissionChartIdMap[chartInfo.SandboxId]; ok {
							continue
						}
						tmpList = append(tmpList, chartInfo)

						if chartInfo.Children != nil {
							for _, thirdChart := range chartInfo.Children {
								// 如果指标不可见,那么就不返回该指标
								if _, ok := noPermissionChartIdMap[chartInfo.SandboxId]; ok {
									continue
								}
								thirdList = append(thirdList, thirdChart)
							}
						}
						thirdInfo.Children = thirdList
						tmpList = append(tmpList, &thirdInfo)
					}
				}
				tmpInfo.Children = tmpList
				tmpNodeList = append(tmpNodeList, &tmpInfo)
			}
		}
		tmpNodeInfo.Children = tmpNodeList
		newAllNodes = append(newAllNodes, &tmpNodeInfo)
	}

	return
}

// AddSandboxV2 新增沙盘
func AddSandboxV2(req request.AddAndEditSandboxV2, opUserId int, opUserName string) (resp *sandbox.SandboxSaveResp, err error) {
	resp = new(sandbox.SandboxSaveResp)
	//沙盘主表信息
	sandboxInfo := &sandbox.Sandbox{
		Name:              utils.TrimStr(req.Name),
		Code:              GenerateCode(),
		Content:           req.Content,
		MindmapData:       req.MindmapData,
		PicUrl:            utils.TrimStr(req.PicUrl),
		SysUserId:         opUserId,
		SysUserName:       opUserName,
		IsDelete:          0,
		ModifyTime:        time.Now(),
		CreateTime:        time.Now(),
		SandboxClassifyId: req.SandboxClassifyId,
		Sort:              0,
		Style:             req.Style,
	}

	//新增沙盘
	id, err := sandbox.AddSandbox(sandboxInfo)
	if err != nil {
		return
	}
	sandboxInfo.SandboxId = int(id)
	resp.Sandbox = sandboxInfo
	return
}

func SandboxItemsMakeTree(allNode []*sandbox.SandboxClassifyItems, sandListMap map[int][]*sandbox.SandboxClassifyItems, sandboxClassifyId int) (nodeAll []*sandbox.SandboxClassifyItems) {
	for k := range allNode {
		if len(allNode[k].Children) > 0 {
			SandboxItemsMakeTree(allNode[k].Children, sandListMap, sandboxClassifyId)
			allNode = append(allNode, sandListMap[allNode[k].ParentId]...)
			nodeAll = allNode
		} else if k == len(allNode)-1 {
			allNode = append(allNode, sandListMap[allNode[k].ParentId]...)
			nodeAll = allNode
		}
	}
	if len(allNode) == 0 {
		nodeAll = append(nodeAll, sandListMap[sandboxClassifyId]...)
	}
	return
}

func SandboxClassifyHaveChild(allNode []*sandbox.SandboxClassifyItems, node *sandbox.SandboxClassifyItems) (childs []*sandbox.SandboxClassifyItems, yes bool) {
	for _, v := range allNode {
		if v.ParentId == node.SandboxClassifyId {
			childs = append(childs, v)
		}
	}
	if len(childs) > 0 {
		yes = true
	}
	return
}

func SandboxClassifyItemsMakeTreeV2(sysUser *system.Admin, allNode []*sandbox.SandboxClassifyItems, node *sandbox.SandboxClassifyItems) {

	childs, _ := sandboxClassifyHaveChildV2(allNode, node) //判断节点是否有子节点并返回
	if len(childs) > 0 {

		node.Children = append(node.Children, childs[0:]...) //添加子节点
		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
			_, has := sandboxClassifyHaveChildV2(allNode, v)
			if has {
				SandboxClassifyItemsMakeTreeV2(sysUser, allNode, v) //递归添加节点
			} else {
				//childrenArr := make([]*sandbox.SandboxClassifyItems, 0)
				//v.Children = childrenArr
			}
		}
	} else {
		//childrenArr := make([]*sandbox.SandboxClassifyItems, 0)
		//node.Children = childrenArr
	}
}

func sandboxClassifyHaveChildV2(allNode []*sandbox.SandboxClassifyItems, node *sandbox.SandboxClassifyItems) (childs []*sandbox.SandboxClassifyItems, yes bool) {
	for _, v := range allNode {
		if v.ParentId == node.SandboxClassifyId && node.SandboxId == 0 {
			childs = append(childs, v)
		}
	}
	if len(childs) > 0 {
		yes = true
	}
	return
}

func GetSandBoxEdbIdsByContent(content string) (edbInfoIds []int, err error) {
	var contentInfo sandbox.ContentDataStruct
	err = json.Unmarshal([]byte(content), &contentInfo)
	if err != nil {
		err = fmt.Errorf("json.Unmarshal err:%s", err.Error())
		return
	}
	// 遍历所有节点
	for _, node := range contentInfo.Cells {
		if node.Data == nil {
			continue
		}
		for _, v := range node.Data.LinkData {
			if v.Type == 1 {
				edbInfoIds = append(edbInfoIds, v.Id)
			}
		}
	}
	return
}
func ReplaceEdbInSandbox(oldEdbInfoId, newEdbInfoId int) (err error) {
	updateTotal := 0
	logMsg := ""
	//分页处理沙盘表
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg("替换沙盘中的指标记录失败提醒,errmsg:"+err.Error(), 3)
		}
		if logMsg != "" {
			utils.FileLog.Info(fmt.Sprintf("替换ETA逻辑的指标记录,替换总数:%d,旧的指标id:%d,新的指标id:%d;%s", updateTotal, oldEdbInfoId, newEdbInfoId, logMsg))
		}
	}()
	//查询沙盘总数
	total, err := sandbox.GetSandboxListCountByCondition("", []interface{}{})
	if err != nil {
		err = fmt.Errorf("查询沙盘总数失败 Err:%s", err)
		return
	}

	// 根据沙盘列表总数,分页查询
	// 计算总页数
	totalPage := (total + 99) / 100 // 使用整数除法,并添加一页以防有余数
	updateSandBox := make([]sandbox.Sandbox, 0)

	//查询沙盘列表
	for i := 0; i < totalPage; i += 1 {
		startSize := i * 100
		list, e := sandbox.GetSandboxListByCondition("", []interface{}{}, startSize, 100)
		if e != nil {
			err = fmt.Errorf("查询沙盘列表失败 Err:%s", e)
			return
		}
		for _, v := range list {
			sandOldEdbId := fmt.Sprintf(`"RId":"1-%d","Id":%d,`, oldEdbInfoId, oldEdbInfoId)
			if strings.Contains(v.Content, sandOldEdbId) {
				sandNewEdbId := fmt.Sprintf(`"RId":"1-%d","Id":%d,`, newEdbInfoId, newEdbInfoId)
				v.Sandbox.Content = strings.ReplaceAll(v.Content, sandOldEdbId, sandNewEdbId)
				updateSandBox = append(updateSandBox, v.Sandbox)
				logMsg += `涉及到的逻辑id:` + strconv.Itoa(v.Sandbox.SandboxId) + ";"
				if len(updateSandBox) > 100 {
					err = sandbox.UpdateSandboxContent(updateSandBox)
					if err != nil {
						err = fmt.Errorf("更新沙盘表失败 Err:%s", err)
						return
					}
					updateTotal += len(updateSandBox)
					updateSandBox = make([]sandbox.Sandbox, 0)
				}
			}
		}
	}
	if len(updateSandBox) > 0 {
		err = sandbox.UpdateSandboxContent(updateSandBox)
		if err != nil {
			err = fmt.Errorf("更新沙盘表失败 Err:%s", err)
			return
		}
		updateTotal += len(updateSandBox)
	}

	return
}

func GetSandboxClassifyByIsShowMe(classifyList []*sandbox.SandboxClassifyItems, classifyId, adminId int) (list []*sandbox.SandboxClassifyItems, err error) {
	sanboxList, err := sandbox.GetSandboxInfoByAdminId(adminId)
	if err != nil {
		return
	}
	existClassify := make(map[int]struct{})
	for _, v := range sanboxList {
		existClassify[v.SandboxClassifyId] = struct{}{}
	}
	for _, v := range classifyList {
		if v.SandboxId > 0 {
			list = append(list, v)
		}
	}
	classifyAll, err := sandbox.GetSandboxClassifyAllIncludeParent()
	if err != nil {
		return
	}
	classifyTree := sandbodClassifyTree(classifyAll, classifyId)
	list = append(list, GetClassifyListRemoveNoSandbox(classifyTree, existClassify)...)
	return
}

func sandbodClassifyTree(classifyList []*sandbox.SandboxClassifyItems, classifyId int) (list []*sandbox.SandboxClassifyItems) {
	for _, v := range classifyList {
		if v.ParentId == classifyId {
			list = append(list, v)
			v.Children = sandbodClassifyTree(classifyList, v.SandboxClassifyId)
		}
	}
	return
}

// GetClassifyListRemoveNoSandbox 去除没有表格的分类
func GetClassifyListRemoveNoSandbox(classifyList []*sandbox.SandboxClassifyItems, sanboxExistClassifyId map[int]struct{}) []*sandbox.SandboxClassifyItems {
	res := make([]*sandbox.SandboxClassifyItems, 0)
	for _, classify := range classifyList {
		if _, ok := sanboxExistClassifyId[classify.SandboxClassifyId]; ok {
			classify.Children = []*sandbox.SandboxClassifyItems{}
			res = append(res, classify)
			continue
		}
		classify.Children = append([]*sandbox.SandboxClassifyItems{}, GetClassifyListRemoveNoSandbox(classify.Children, sanboxExistClassifyId)...)
		if len(classify.Children) > 0 {
			classify.Children = []*sandbox.SandboxClassifyItems{}
			res = append(res, classify)
		}
	}
	return res
}