package service

import (
	"strings"

	"be.ems/src/framework/utils/parse"
	"be.ems/src/modules/chart/model"
	chartRepository "be.ems/src/modules/chart/repository"
	"github.com/goccy/go-json"
)

// 实例化服务层 ChartGraphImpl 结构体
var NewChartGraphImpl = &ChartGraphImpl{
	graphRepository: chartRepository.NewChartGraphImpl,
}

// ChartGraphImpl G6关系图数据表 服务层处理
type ChartGraphImpl struct {
	// G6关系图数据服务
	graphRepository chartRepository.IChartGraph
}

// SelectGroup 查询组名
func (s *ChartGraphImpl) SelectGroup() []string {
	return s.graphRepository.SelectGroup()
}

// LoadData 查询所组图数据
func (s *ChartGraphImpl) LoadData(rowGroup, rowType string) map[string]any {
	// 查询数据
	graph := model.ChartGraph{
		RowGroup: rowGroup,
	}
	if rowType != "" {
		graph.RowType = rowType
	}
	data := s.graphRepository.SelectList(graph)

	// 数据项
	nodes := []map[string]any{}
	edges := []map[string]any{}
	combos := []map[string]any{}

	for _, v := range data {
		if v.RowType == "node" {
			nodes = append(nodes, s.loadNode(v))
		}
		if v.RowType == "edge" {
			edges = append(edges, s.loadEdge(v))
		}
		if v.RowType == "combo" {
			combos = append(combos, s.loadCombo(v))
		}
	}

	return map[string]any{
		"nodes":  nodes,
		"edges":  edges,
		"combos": combos,
	}
}

// loadNode 图数据Node
func (s *ChartGraphImpl) loadNode(v model.ChartGraph) map[string]any {
	node := map[string]any{
		"id":      v.ID,
		"comboId": v.ComboID,
		"x":       v.X,
		"y":       v.Y,
		"type":    v.Type,
		"depth":   v.Depth,
	}

	// 元素样式
	style := map[string]any{}
	if len(v.Style) > 7 {
		json.Unmarshal([]byte(v.Style), &style)
	}
	node["style"] = style

	// 元素大小
	if strings.Contains(v.Size, "[") {
		sizeArr := []int64{}
		json.Unmarshal([]byte(v.Size), &sizeArr)
		node["size"] = sizeArr
	} else {
		node["size"] = parse.Number(v.Size)
	}

	// 标签文本
	node["label"] = v.Label
	labelCfg := map[string]any{}
	if len(v.LabelCfg) > 7 {
		json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
	}
	node["labelCfg"] = labelCfg

	// 三角形属性
	if v.Type == "triangle" {
		node["direction"] = v.Direction
	}

	// 图片属性
	if strings.Index(v.Type, "image") == 0 {
		node["img"] = v.Img
		clipCfg := map[string]any{}
		if len(v.ClipCfg) > 7 {
			json.Unmarshal([]byte(v.ClipCfg), &clipCfg)
		}
		node["clipCfg"] = clipCfg
	}

	// 图标属性
	if v.Icon != "" {
		icon := map[string]any{}
		if len(v.Icon) > 7 {
			json.Unmarshal([]byte(v.Icon), &icon)
		}
		node["icon"] = icon
	}

	return node
}

// loadEdge 图数据Edge
func (s *ChartGraphImpl) loadEdge(v model.ChartGraph) map[string]any {
	edge := map[string]any{
		"id":     v.ID,
		"source": v.Source,
		"target": v.Target,
		"type":   v.Type,
	}

	// 元素样式
	style := map[string]any{}
	if len(v.Style) > 7 {
		json.Unmarshal([]byte(v.Style), &style)
	}
	edge["style"] = style

	// 标签文本
	edge["label"] = v.Label
	labelCfg := map[string]any{}
	if len(v.LabelCfg) > 7 {
		json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
	}
	edge["labelCfg"] = labelCfg

	return edge
}

// loadCombo 图数据Combo
func (s *ChartGraphImpl) loadCombo(v model.ChartGraph) map[string]any {
	combo := map[string]any{
		"id":    v.ID,
		"x":     v.X,
		"y":     v.Y,
		"type":  v.Type,
		"depth": v.Depth,
	}

	// 元素样式
	style := map[string]any{}
	if len(v.Style) > 7 {
		json.Unmarshal([]byte(v.Style), &style)
	}
	combo["style"] = style

	// 元素大小
	if strings.Contains(v.Size, "[") {
		sizeArr := []int64{}
		json.Unmarshal([]byte(v.Size), &sizeArr)
		combo["size"] = sizeArr
	} else {
		combo["size"] = parse.Number(v.Size)
	}

	// 元素内边距
	if strings.Contains(v.Padding, "[") {
		paddingArr := []int64{}
		json.Unmarshal([]byte(v.Padding), &paddingArr)
		combo["padding"] = paddingArr
	} else {
		combo["padding"] = parse.Number(v.Padding)
	}

	// 标签文本
	combo["label"] = v.Label
	labelCfg := map[string]any{}
	if len(v.LabelCfg) > 7 {
		json.Unmarshal([]byte(v.LabelCfg), &labelCfg)
	}
	combo["labelCfg"] = labelCfg

	// 分组内元素
	if v.Children != "" {
		children := []map[string]any{}
		if len(v.Children) > 7 {
			json.Unmarshal([]byte(v.Children), &children)
		}
		combo["children"] = children
	}

	return combo
}

// SaveData 添加组图数据
func (s *ChartGraphImpl) SaveData(rowGroup string, data map[string]any) int64 {
	graphs := []model.ChartGraph{}
	nodes := data["nodes"].([]map[string]any)
	graphNodes := s.saveNode(rowGroup, nodes)
	graphs = append(graphs, graphNodes...)
	edges := data["edges"].([]map[string]any)
	graphEdges := s.saveEdge(rowGroup, edges)
	graphs = append(graphs, graphEdges...)
	combos := data["combos"].([]map[string]any)
	graphCombos := s.saveCombo(rowGroup, combos)
	graphs = append(graphs, graphCombos...)
	// 删除组数据后插入
	if len(graphs) > 0 {
		s.graphRepository.DeleteGroup(rowGroup)
	}
	return s.graphRepository.Inserts(graphs)
}

// saveNode 图数据Node
func (s *ChartGraphImpl) saveNode(rowGroup string, nodes []map[string]any) []model.ChartGraph {
	var graphs []model.ChartGraph
	for _, v := range nodes {
		node := model.ChartGraph{
			RowType:  "node",
			RowGroup: rowGroup,
			ID:       v["id"].(string),
			X:        v["x"].(float64),
			Y:        v["y"].(float64),
			Type:     v["type"].(string),
		}
		if comboId, ok := v["comboId"]; ok && comboId != nil {
			node.ComboID = comboId.(string)
		}
		if depth, ok := v["depth"]; ok && depth != nil {
			node.Depth = int(depth.(float64))
		}
		if styleByte, err := json.Marshal(v["style"]); err == nil {
			node.Style = string(styleByte)
		}

		// 元素大小
		if sizeByte, err := json.Marshal(v["size"]); err == nil {
			node.Size = string(sizeByte)
		}

		// 标签文本
		if label, ok := v["label"]; ok && label != nil {
			node.Label = label.(string)
		}
		if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
			node.LabelCfg = string(labelCfgByte)
		}
		// 三角形属性
		if direction, ok := v["direction"]; ok && direction != nil && node.Type == "triangle" {
			node.Direction = direction.(string)
		}
		// 图片属性
		if img, ok := v["img"]; ok && img != nil {
			node.Img = img.(string)
			if clipCfgByte, err := json.Marshal(v["clipCfg"]); err == nil {
				node.ClipCfg = string(clipCfgByte)
			}
		}
		// 图标属性
		if icon, ok := v["icon"]; ok && icon != nil {
			if iconByte, err := json.Marshal(icon); err == nil {
				node.Icon = string(iconByte)
			}
		}

		graphs = append(graphs, node)
	}
	return graphs
}

// saveEdge 图数据Edge
func (s *ChartGraphImpl) saveEdge(rowGroup string, edges []map[string]any) []model.ChartGraph {
	var graphs []model.ChartGraph
	for _, v := range edges {
		edge := model.ChartGraph{
			RowType:  "edge",
			RowGroup: rowGroup,
			ID:       v["id"].(string),
			Source:   v["source"].(string),
			Target:   v["target"].(string),
			Type:     v["type"].(string),
		}

		if styleByte, err := json.Marshal(v["style"]); err == nil {
			edge.Style = string(styleByte)
		}

		// 标签文本
		if label, ok := v["label"]; ok && label != nil {
			edge.Label = label.(string)
		}
		if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
			edge.LabelCfg = string(labelCfgByte)
		}

		graphs = append(graphs, edge)
	}
	return graphs
}

// saveCombo 图数据Combo
func (s *ChartGraphImpl) saveCombo(rowGroup string, combos []map[string]any) []model.ChartGraph {
	var graphs []model.ChartGraph
	for _, v := range combos {
		combo := model.ChartGraph{
			RowType:  "combo",
			RowGroup: rowGroup,
			ID:       v["id"].(string),
			X:        v["x"].(float64),
			Y:        v["y"].(float64),
			Type:     v["type"].(string),
		}
		if depth, ok := v["depth"]; ok && depth != nil {
			combo.Depth = int(depth.(float64))
		}
		if styleByte, err := json.Marshal(v["style"]); err == nil {
			combo.Style = string(styleByte)
		}
		if paddingByte, err := json.Marshal(v["padding"]); err == nil {
			combo.Padding = string(paddingByte)
		}
		if childrenByte, err := json.Marshal(v["children"]); err == nil {
			combo.Children = string(childrenByte)
		}

		// 元素大小
		if sizeByte, err := json.Marshal(v["size"]); err == nil {
			combo.Size = string(sizeByte)
		}

		// 标签文本
		if label, ok := v["label"]; ok && label != nil {
			combo.Label = label.(string)
		}
		if labelCfgByte, err := json.Marshal(v["labelCfg"]); err == nil {
			combo.LabelCfg = string(labelCfgByte)
		}

		graphs = append(graphs, combo)
	}
	return graphs
}

// Delete 删除所组图数据
func (s *ChartGraphImpl) DeleteGroup(rowGroup string) int64 {
	return s.graphRepository.DeleteGroup(rowGroup)
}
