package executor

import (
	"encoding/json"
	"strconv"
	"strings"
	"wdd.io/agent-go/status"
)

func BuildAgentOsOperator(agentInfo *status.AgentInfo, ossOfflinePrefix string) *AgentOsOperator {

	AgentOsOperatorCache = &AgentOsOperator{
		InstallCommandPrefix: []string{
			"apt-get", "install", "--allow-downgrades", "-y",
		},
		RemoveCommandPrefix: []string{"apt", "remove", "-y"},
		CanAccessInternet:   true,
		IsOsTypeUbuntu:      true,
		IsOsTypeCentOS:      false,
		IsOsTypeEuler:       false,
		IsAgentInnerWall:    false,
		AgentArch:           "amd64",
		AgentOSReleaseCode:  "focal",
		AgentServerInfo:     nil,
		OssOfflinePrefix:    ossOfflinePrefix,
	}

	// os type
	detectByAgentStatusInfo(agentInfo, AgentOsOperatorCache)

	// internet
	detectByInternet(AgentOsOperatorCache)

	return AgentOsOperatorCache
}

func detectByAgentStatusInfo(agentInfo *status.AgentInfo, os *AgentOsOperator) {
	if agentInfo == nil {
		log.WarnF("[detectByAgentStatusInfo] - agentInfo from status module is nil, roll back to traditional way!")
		// detectByOsType()
	}

	bytes, _ := json.Marshal(agentInfo)
	log.DebugF("[detectByAgentStatusInfo] - agent info is => %s", string(bytes))

	if strings.Contains(agentInfo.HostInfo.Platform, "openeuler") || strings.Contains(agentInfo.HostInfo.PlatformFamily, "rehl") {
		// centos
		os.IsOsTypeUbuntu = false
		os.IsOsTypeCentOS = true
		if strings.Contains(agentInfo.HostInfo.Platform, "openeuler") {
			os.IsOsTypeEuler = true
		}
		os.InstallCommandPrefix = []string{
			"yum", "install", "-y",
		}
		os.RemoveCommandPrefix = []string{
			"yum", "remove", "-y",
		}

	} else if strings.Contains(agentInfo.HostInfo.PlatformFamily, "debian") {
		// ubuntu
		os.IsOsTypeUbuntu = true
		os.IsOsTypeCentOS = false
		os.IsOsTypeEuler = false
		os.RemoveCommandPrefix = []string{"apt", "remove", "-y"}
		os.InstallCommandPrefix = []string{
			"apt-get", "install", "--allow-downgrades", "-y",
		}

		// os release code
		os.AgentOSReleaseCode = judgeUbuntuReleaseFromOsVersion(agentInfo.HostInfo.PlatformVersion)
	}

	// agent cpu arch
	os.AgentArch = judgeAgentCpuArchByKernelArch(agentInfo.HostInfo.KernelArch)

}

func judgeUbuntuReleaseFromOsVersion(osVersion string) string {

	switch osVersion {
	case "16.04":
		return "xenial"
	case "18.04":
		return "bionic"
	case "20.04":
		return "focal"
	case "22.04":
		return "jammy"
	default:
		return "ubuntu-unknown"
	}
}

func judgeAgentCpuArchByKernelArch(kernelArch string) string {
	switch kernelArch {
	case "x86_64":
		return "amd64"
	case "aarch64":
		return "arm64"
	case "armv8":
		return "arm64"
	case "armv6":
		return "arm6"
	case "armv7":
		return "arm7"
	case "i32":
		return "386"
	case "i86":
		return "386"
	default:
		return "cpu-unknown"
	}
}

func detectByInternet(os *AgentOsOperator) {

	outsideTestUrl := "www.google.com"
	innerTestUrl := "www.baidu.com"

	testInternetCommand := []string{
		"curl",
		"-o",
		"/dev/null",
		"-m",
		"5",
		"-s",
	}

	if PureResultSingleExecute(append(testInternetCommand, outsideTestUrl)) {
		os.CanAccessInternet = true
		os.IsAgentInnerWall = false
	} else if PureResultSingleExecute(append(testInternetCommand, innerTestUrl)) {
		os.CanAccessInternet = true
		os.IsAgentInnerWall = true
	} else {
		os.CanAccessInternet = false
		os.IsAgentInnerWall = true
	}

	log.InfoF("[Agent Network Status] - Can Access Internet => %s  Inner CN => %s", strconv.FormatBool(os.CanAccessInternet), strconv.FormatBool(os.IsAgentInnerWall))

}

func detectByOsType(os *AgentOsOperator, osInfo string) {

	ubuntuOsReleaseCode := [][]string{
		{
			"cat",
			"/etc/os-release",
		},
		{
			"grep",
			"CODE",
		},
		{
			"head",
			"-1",
		},
		{
			"cut",
			"-d",
			"=",
			"-f",
			"2",
		},
	}

	if strings.HasPrefix(osInfo, "Ce") {
		// centos
		os.IsOsTypeUbuntu = false
		os.InstallCommandPrefix = []string{
			"yum", "install", "-y",
		}
		os.RemoveCommandPrefix = []string{
			"yum", "remove",
		}

	} else {
		// ubuntu
		os.IsOsTypeUbuntu = true
		os.RemoveCommandPrefix = []string{"apt", "remove", "-y"}
		os.InstallCommandPrefix = []string{
			"apt-get", "install", "--allow-downgrades", "-y",
		}

		// os release code
		ok, resultLog := PipelineCommandExecutor(ubuntuOsReleaseCode)
		if ok {
			os.AgentOSReleaseCode = resultLog[0]
		} else {
			os.AgentOSReleaseCode = "UNKNOWN"
		}

	}

}
