/*
 * Copyright (c) KylinSoft  Co., Ltd. 2024.All rights reserved.
 * ha-api licensed under the Mulan Permissive Software License, Version 2.
 * See LICENSE file for more details.
 * Author: bixiaoyan <bixiaoyan@kylinos.cn>
 * Date: Thu Mar 27 09:32:28 2025 +0800
 */

package models

import (
	"bufio"
	"encoding/json"
	"encoding/xml"
	"fmt"
        "slices"

	"strings"

	"gitee.com/openeuler/ha-api/utils"
	"github.com/chai2010/gettext-go"
)

type TagInfo struct {
	ID      string      `json:"id"`
	TagsRsc interface{} `json:"tagsrsc"`
}

type Tag struct {
	ID      string   `xml:"id,attr"`
	ObjRefs []ObjRef `xml:"obj_ref"`
}
type ObjRef struct {
	ID string `xml:"id,attr"`
}
type Tags struct {
	Tags []Tag `xml:"tag"`
}

type TagPostData struct {
	ID           string   `json:"id"`
	Tag_resource []string `json:"tag_resource"`
}

type TagGetResult struct {
	Action  bool      `json:"action"`
	Data    []TagInfo `json:"data"`
	ResList []string  `json:"res_list"`
	Error   string    `json:"error,omitempty"`
}

func GetOneTag(tagName string) map[string]interface{} {
	result := make(map[string]interface{})
	var data TagPostData
	cmd := "pcs tag config " + tagName
	out, err := utils.RunCommand(cmd)
	if err != nil {
		result["action"] = false
		result["error"] = "Can not get the tag!"
		return result
	}
	scanner := bufio.NewScanner(strings.NewReader(string(out)))
	//跳过第一行
	scanner.Scan()
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line != "" {
			data.Tag_resource = append(data.Tag_resource, line)
		}
	}
	data.ID = tagName
	result["action"] = true
	result["data"] = data
	return result

}
func GetTag() TagGetResult {
	resList := []string{}
	cmd := "cibadmin --query --scope tags"
	rsc_info := GetResourceInfo()

	for _, res := range rsc_info["data"].([]map[string]interface{}) {
		resList = append(resList, res["id"].(string))
	}

	out, err := utils.RunCommand(cmd)

	if err != nil {
		if strings.Contains(string(out), "No such device or address") {
			return TagGetResult{Action: true, Data: []TagInfo{}, ResList: resList}
		} else {
			return TagGetResult{Action: false, Error: gettext.Gettext("Get tag failed")}
		}

	}

	// 解析tag数据
	var tags Tags
	if err := xml.Unmarshal([]byte(out), &tags); err != nil {
		return TagGetResult{Action: false, Error: gettext.Gettext("Parsing JSON failed")}
	}

	tagInfos := make([]TagInfo, len(tags.Tags))

	for i, tag := range tags.Tags {
		var tagList []interface{}
		for _, test := range tag.ObjRefs {
			for _, res := range rsc_info["data"].([]map[string]interface{}) {
				if res["id"].(string) == test.ID {
					tagList = append(tagList, res)
					break
				}
			}
		}
		tagInfos[i] = TagInfo{
			ID: tag.ID,
			//TagsRsc: tag.ObjRefs,
			TagsRsc: tagList,
		}
	}

	return TagGetResult{Action: true, Data: tagInfos, ResList: resList}
}

func SetTag(data []byte) utils.GeneralResponse {
	
	var result utils.GeneralResponse
	// json数据解析
	if len(data) == 0 {
		result.Action = false
		result.Error = gettext.Gettext("No input data")
		return result
	}
	var TagData TagPostData
	err := json.Unmarshal(data, &TagData)
	if err != nil {
		result.Action = false
		result.Error = gettext.Gettext("Cannot convert data to json map")
		return result
	}

	nameCmd := "pcs resource config |awk '/Resource|Group|Bundle/ {print $2}'"
	names, _ := utils.RunCommand(nameCmd)
	standards := strings.Split(strings.TrimSpace(string(names)), "\n")
	nameCmd = "pcs tag |awk '!/^[ \t]/'"
	names, _ = utils.RunCommand(nameCmd)
	tagNames := strings.Split(strings.TrimSpace(string(names)), "\n")
	standards = append(standards, tagNames...)
	if slices.Contains(standards, TagData.ID) {
		result.Action = false
		result.Error = fmt.Sprintf(gettext.Gettext("The tag name %s is already in the cluster!"), TagData.ID)
		return result
	}

	cmd := "pcs tag create " + TagData.ID
	for _, res := range TagData.Tag_resource {
		cmd = cmd + " " + string(res)
	}
	out, err := utils.RunCommand(cmd)
	if err == nil {
		result.Action = true
		result.Info = gettext.Gettext("Add tag success")
	} else {
		result.Action = false
		result.Error = string(out)
	}
	return result
}

func UpdateTag(tagName string, data []byte) utils.GeneralResponse {
	var result utils.GeneralResponse
	// json数据解析
	if len(data) == 0 {
		result.Action = false
		result.Error = gettext.Gettext("No input data")
		return result
	}
	var TagData TagPostData
	err := json.Unmarshal(data, &TagData)
	if err != nil {
		result.Action = false
		result.Error = gettext.Gettext("Cannot convert data to json map")
		return result
	}
	cmd_create := "pcs tag create " + string(tagName)
	cmd_delete := "pcs tag delete " + string(tagName)
	for _, res := range TagData.Tag_resource {
		cmd_create = cmd_create + " " + string(res)
	}
	out1, err1 := utils.RunCommand(cmd_delete)
	if err1 == nil {
		out2, err2 := utils.RunCommand(cmd_create)
		if err2 == nil {
			result.Action = true
			result.Info = gettext.Gettext("Update tag success")
		} else {
			result.Action = false
			result.Error = string(out2)
		}

	} else {
		result.Action = false
		result.Error = string(out1)
	}
	return result
}

func TagAction(tagName string, action string) utils.GeneralResponse {
	var result utils.GeneralResponse
	cmd := "pcs resource "
	if action == "delete" {
		return DeleteTag(tagName)
	} else if action == "start" {
		cmd = cmd + "enable " + tagName
	} else if action == "stop" {
		cmd = cmd + "disable " + tagName
	}
	print(cmd)
	out, err := utils.RunCommand(cmd)
	if err == nil {
		result.Action = true
		result.Info = gettext.Gettext("Tag action success")
	} else {
		result.Action = false
		result.Error = string(out)
	}
	return result
}

func DeleteTag(tagName string) utils.GeneralResponse {
	var result utils.GeneralResponse
	cmd := "pcs tag delete " + tagName
	out, err := utils.RunCommand(cmd)
	if err == nil {
		result.Action = true
		result.Info = gettext.Gettext("Delete tag success")
	} else {
		result.Action = false
		result.Error = string(out)
	}
	return result
}