package op

import (
	"agent-wdd/host_info"
	"agent-wdd/log"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

type PackageOperator struct {
	installPrefix []string // 安装前缀
	removePrefix  []string // 移除前缀
	upgradePrefix []string // 升级前缀
	initCommand   []string
}

var (
	AgentPackOperator  = &PackageOperator{}
	aptPackageOperator = &PackageOperator{
		installPrefix: []string{
			"apt-get", "install", "--allow-downgrades", "-y",
		},
		removePrefix: []string{
			"apt", "remove", "-y",
		},
		upgradePrefix: []string{},
		initCommand: []string{
			"apt-get", "update",
		},
	}
	yumPackageOperator = &PackageOperator{
		installPrefix: []string{
			"yum", "install", "-y",
		},
		removePrefix: []string{
			"yum", "remove", "-y",
		},
		upgradePrefix: []string{},
		initCommand: []string{
			"yum", "makecache",
		},
	}
)

func (op *PackageOperator) Install(tools []string) bool {
	// 判定本机的包管理Operator
	ok := generatePackageOperator()
	if !ok {
		log.Error("PackageOperator init failed! 无法执行安装操作 %s", tools)
		return false
	}

	// install seperately
	for _, tool := range tools {
		ok, result := SingleLineCommandExecutor(append(AgentPackOperator.installPrefix, tool))
		if !ok {
			log.Error("[install] failed! => %s", tool)
		}

		// 打印安装的过程内容
		beautifulPrintListWithTitle(result, fmt.Sprintf("安装 %s 的过程内容", tool))

	}

	return true
}

// PackageInit 初始化包管理器, 同样会判定主机是否可以联网，如果本机是ubuntu或者debian, 则使用apt, 否则使用yum
func (op *PackageOperator) PackageInit() bool {
	log.Info("PackageInit !")

	// beautifulPrintListWithTitle(host_info.ConfigCache)

	// package init
	os := host_info.ConfigCache.Agent.OS

	if os.PackInit {
		log.Info("PackageInit already done! skip!")
		return true
	}

	// 判定本机的包管理Operator
	ok := generatePackageOperator()
	if !ok {
		return false
	}

	os.PackInit = true
	os.SaveConfig()

	if os.IsUbuntuType {
		ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
		if !ok {
			log.Error("APT init failed! please check ! %s", resultLog)
		}
	}

	return true

}

func (op *PackageOperator) PackageInitForce() bool {

	log.Info("PackageInitForce !")

	os := host_info.ConfigCache.Agent.OS

	if os.IsUbuntuType {
		ok, resultLog := SingleLineCommandExecutor(aptPackageOperator.initCommand)
		if !ok {
			log.Error("APT init failed! please check ! %s", resultLog)
		}
		log.Info("APT init success! %s", resultLog)
	}

	return true
}

func (op *PackageOperator) Remove(tools []string) {
	// 判定本机的包管理Operator
	generatePackageOperator()

	// install seperately
	for _, tool := range tools {
		ok, result := SingleLineCommandExecutor(append(AgentPackOperator.removePrefix, tool))
		if !ok {
			log.Error("[remove] failed! => %s", tool)
			beautifulPrintListWithTitle(result, fmt.Sprintf("移除 %s 的过程内容", tool))
		}
	}

}

func generatePackageOperator() bool {

	// cache return
	if AgentPackOperator.initCommand != nil {
		log.Info("PackageOperator init success! %v", AgentPackOperator.initCommand)
		return true
	}

	// 检查是否可以连接互联网
	if host_info.CanConnectInternet() <= 1 {
		log.Error("服务器无法连接互联网，无法初始化包管理器")
		return false
	}

	// 检查本机是否存在OS的信息
	os := host_info.ConfigCache.Agent.OS
	if os.Hostname == "" {
		os.Gather()
		os.SaveConfig()
	}

	if os.IsUbuntuType {
		log.Info("Ubuntu type detected! use apt package operator!")
		AgentPackOperator = aptPackageOperator
	} else {
		log.Info("Other type detected! use yum package operator!")
		AgentPackOperator = yumPackageOperator
	}

	return true
}

// GetLatestGithubReleaseVersion 获取GitHub仓库的最新版本
func GetLatestGithubReleaseVersion(repoOwner, repoName string) (string, error) {
	// 检查是否可以连接互联网
	if host_info.CanConnectInternet() <= 1 {
		return "", fmt.Errorf("服务器无法连接互联网，无法获取GitHub最新版本")
	}

	// 设置超时时间为10秒的HTTP客户端
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	// 构建GitHub API URL
	apiURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", repoOwner, repoName)

	// 发送GET请求
	resp, err := client.Get(apiURL)
	if err != nil {
		return "", fmt.Errorf("请求GitHub API失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("GitHub API返回非200状态码: %d", resp.StatusCode)
	}

	// 读取响应体
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应内容失败: %v", err)
	}

	// 解析JSON响应
	var release struct {
		TagName string `json:"tag_name"`
	}

	if err := json.Unmarshal(body, &release); err != nil {
		return "", fmt.Errorf("解析JSON响应失败: %v", err)
	}

	return release.TagName, nil
}

// CommandExists 判定命令是否存在
func CommandExists(command string) bool {
	ok, _ := SingleLineCommandExecutor([]string{"command", "-v", command})
	return ok
}

func CommandExistsByPath(command string) bool {

	// 查询 /usr/bin /usr/local/bin中是否有可执行文件
	_, result := SingleLineCommandExecutor([]string{"find", "/usr/bin", "/usr/local/bin", "-name", command})
	if result == nil || len(result) == 0 {
		return false
	}

	return true
}

func beautifulPrintListWithTitle(contend []string, title string) {

	fmt.Println()
	fmt.Println(">>>>>>>>  " + title + "  <<<<<<<<")
	for _, line := range contend {
		if line == "EOF" {
			// do nothing
			continue
		}
		fmt.Println(line)
	}
	fmt.Println(">>>>>>>>  end  <<<<<<<<")
	fmt.Println()
}
