package node

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/coroot/coroot-node-agent/flags"
	"github.com/coroot/coroot-node-agent/kube"
	"github.com/coroot/coroot-node-agent/utils"
	. "github.com/coroot/coroot-node-agent/utils/modelse"
	klog "github.com/sirupsen/logrus"
	"gopkg.in/ini.v1"
	"strconv"
	"strings"
)

func NewNodeInfo(name, kv, version string) (*NodeInfoT, error) {
	if *flags.RunInOmniagent {
		klog.Infof("run in omniagent.")
		ni, err := newNodeInfoFromCommonIni(name, kv, version)
		if err != nil {
			klog.Errorf("Failed to create node info from common ini: %v", err)
			return nil, err
		}
		return ni, nil
	}

	var ip string
	var err error
	if *flags.RunInContainer {
		klog.Infof("run in container.")
		ip, err = kube.GetNodeIpByCore(name)
		if err != nil {
			return nil, err
		}
	} else {
		klog.Infof("run standalone.")
		ip, err = utils.GetRealIp()
		if err != nil {
			return nil, err
		}
	}

	n := &NodeInfoT{
		Hostname:      name,
		HostIp:        ip,
		KernelVersion: kv,
		SystemUUID:    utils.SystemUUID(),
		HostID:        utils.GetHostID(),
		AccountID:     utils.GetAccountID(),
		LicenseKey:    *flags.LicenseKey,
		AgentVersion:  version,
		SysTag:        *flags.SysTag,
	}
	utils.SaveNodeInfo(n)
	return n, nil
}

func newNodeInfoFromCommonIni(name, kv, version string) (*NodeInfoT, error) {
	if *flags.CommonIni != "" {
		iniData, err := ini.Load(*flags.CommonIni)
		if err != nil {
			klog.Errorf("Failed to load common ini file: %v", err)
			return nil, err
		}
		if iniData == nil {
			return nil, fmt.Errorf("no ini data")
		}
		ip := iniData.Section("common").Key("ip").String()
		uuid := iniData.Section("common").Key("system_uuid").String()
		host_id, err := iniData.Section("common").Key("host_id").Int64()
		if err != nil {
			klog.Errorf("Failed to get host_id: %v", err)
			return nil, err
		}
		token := iniData.Section("common").Key("token").String()
		account_and_user_byte, err := base64.StdEncoding.DecodeString(token)
		if err != nil {
			return nil, err
		}
		account_and_user_string := strings.Split(string(account_and_user_byte), "@")
		if len(account_and_user_string) > 0 {
			sysTag := ""
			tagsStr := iniData.Section("common").Key("tags").String()
			if tagsStr != "" {
				tagT := struct {
					HostTag struct {
						SystemTag []string `json:"sys"`
					} `json:"host_tag"`
				}{}
				err := json.Unmarshal([]byte(tagsStr), &tagT)
				if err != nil {
					return nil, err
				}
				sysTag = strings.Join(tagT.HostTag.SystemTag, ",")
			}
			accountId, err := strconv.Atoi(account_and_user_string[0])
			if err == nil {
				n := &NodeInfoT{
					Hostname:      name,
					HostIp:        ip,
					KernelVersion: kv,
					SystemUUID:    uuid,
					HostID:        host_id,
					AccountID:     accountId,
					LicenseKey:    *flags.LicenseKey,
					AgentVersion:  version,
					SysTag:        sysTag,
				}
				utils.SaveNodeInfo(n)
				return n, nil
			} else {
				klog.Errorf("Failed to strconv accountId: %v", err)
				return nil, err
			}
		}
	}
	return nil, nil
}
