package a_executor

import (
	"fmt"
	"strings"
	"wdd.io/agent-common/image"
)

var LocalGzipImageFolderPrefix = "/var/lib/docker/image_sync/"
var DefaultSocks5ProxyUser = "zeaslity"
var DefaultSocks5ProxyPass = "password"

func (op *AgentOsOperator) Sync(baseFuncName string, funcArgs ...string) (bool, []string) {
	resultOk := false
	var errorLog []string

	switch baseFuncName {

	case "DOWNLOAD_DOCKER_IMAGE":
		resultOk, errorLog = op.downloadDockerImage(funcArgs)
		break
	case "COMPRESS_IMAGE_TO_GZIP":
		resultOk, errorLog = op.compressImageToGzip(funcArgs)
		break
	case "UPLOAD_GZIP_TO_OSS":
		resultOk, errorLog = op.uploadGzipFileToOss(funcArgs)
		break
	case "DOWNLOAD_GZIP_IMAGE_FILE":
		resultOk, errorLog = op.downloadGzipImageFile(funcArgs)
		break
	case "LOAD_DOCKER_IMAGE_FROM_GZIP":
		resultOk, errorLog = op.loadDockerImageFromGzip(funcArgs)
		break
	case "PUSH_IMAGE_TO_TARGET_HARBOR":
		resultOk, errorLog = op.pushImageToTargetHarbor(funcArgs)
		break
	case "UPDATE_IMAGE_TAG":
		resultOk, errorLog = op.updateImageTag(funcArgs)
		break
	default:
		resultOk, errorLog = op.okExec(funcArgs)
	}

	return resultOk, errorLog
}

func (op *AgentOsOperator) downloadDockerImage(funcArgs []string) (bool, []string) {
	// funcArgs are imageFullName gzipFolderPrefix gzipFileName ossUrlPrefix namespace newImageTag

	if !BasicCommandExistByPath("docker") {
		return false, []string{
			"docker not exits !",
		}
	}
	imageFullName := funcArgs[0]
	log.InfoF("[downloadDockerImage]- start to pull docker image %s", imageFullName)

	// login
	if strings.HasPrefix(imageFullName, image.CmiiHarborPrefix) {
		HardCodeCommandExecutor("docker login -u rad02_drone -p Drone@1234 harbor.cdcyy.com.cn")
	}

	if !PureResultSingleExecute([]string{
		"docker",
		"pull",
		imageFullName,
	}) {
		return false, []string{
			"docker pull failed of " + imageFullName,
		}
	}

	if !BasicDockerImageExistByFullName(funcArgs[0]) {
		return false, []string{
			"image not exits ! unknown error happened!",
		}
	}
	return true, []string{
		imageFullName,
	}
}

func (op *AgentOsOperator) compressImageToGzip(funcArgs []string) (bool, []string) {
	if !BasicCommandExistByPath("docker") {
		return false, []string{
			"docker not exits !",
		}
	}
	if !BasicCommandExistByPath("gzip") {
		return false, []string{
			"gzip not exits !",
		}
	}

	gzipFolderPrefix := funcArgs[1]
	if !BasicFolderExists(gzipFolderPrefix) {
		BasicCreateFolder(gzipFolderPrefix)
	}

	imageFullName := funcArgs[0]
	if !BasicDockerImageExistByFullName(imageFullName) {
		return false, []string{
			"image not exits !",
		}
	}

	if !strings.HasSuffix(gzipFolderPrefix, "/") {
		gzipFolderPrefix += "/"
	}

	gzipImageFromFullName := image.ImageFullNameToGzipFileName(imageFullName)
	dockerSaveCommand := "docker save " + imageFullName + " | gzip > " + gzipFolderPrefix + gzipImageFromFullName

	executor, i := HardCodeCommandExecutor(dockerSaveCommand)
	if !executor {
		return false, i
	}

	if !BasicFileExistAndNotNull(gzipFolderPrefix + gzipImageFromFullName) {
		return false, []string{
			"gzip of ile error ",
		}
	}

	return true, []string{
		gzipImageFromFullName,
	}
}

func (op *AgentOsOperator) uploadGzipFileToOss(funcArgs []string) (bool, []string) {

	if !BasicCommandExistByPath("mc") {
		return false, []string{
			"mc not exits!",
		}
	}

	gzipFolderPrefix := funcArgs[1]
	gzipImageFromFullName := funcArgs[2]

	ok, resultLog := HardCodeCommandExecutor("mc --insecure alias set demo https://oss.ig-demo.uavcmlc.com cmii B#923fC7mk")
	//ok, resultLog = HardCodeCommandExecutor("mc alias list")

	PureResultSingleExecute([]string{
		"mc",
		"rm",
		"demo/cmlc-installation/tmp/" + gzipImageFromFullName,
	})

	ok, resultLog = AllCommandExecutor([]string{
		"mc",
		"cp",
		gzipFolderPrefix + gzipImageFromFullName,
		"demo/cmlc-installation/tmp/" + gzipImageFromFullName,
	})
	if !ok {
		return false, resultLog
	}

	find, _ := BasicFindContentInCommandOutput("mc ls demo/cmlc-installation/tmp/", gzipImageFromFullName)
	if !find {
		return false, []string{
			"demo oss can't find gzip file !",
		}
	}

	return true, []string{
		gzipImageFromFullName,
	}

}

func (op *AgentOsOperator) downloadGzipImageFile(funcArgs []string) (bool, []string) {

	ossUrlPrefix := funcArgs[3]
	gzipImageFromFullName := funcArgs[2]
	proxyUrl := funcArgs[4]

	// create folder
	BasicCreateFolder(LocalGzipImageFolderPrefix)

	// remove file
	desFile := LocalGzipImageFolderPrefix + gzipImageFromFullName

	if !BasicRemoveFileOrFolder(desFile) {
		return false, []string{
			"file already exits ! can't remove it!",
		}
	}

	//var download bool
	//var downloadLog []string
	//if proxyUrl == "" {
	//	download, downloadLog = BasicDownloadFileByCurl(ossUrlPrefix+gzipImageFromFullName, desFile)
	//} else {
	//	 = BasicDownloadFileWithProxy(ossUrlPrefix+gzipImageFromFullName, proxyUrl, desFile)
	//}

	download, downloadLog := BasicDownloadFile(ossUrlPrefix+gzipImageFromFullName, proxyUrl, DefaultSocks5ProxyUser, DefaultSocks5ProxyPass, desFile)
	if !download {
		return false, downloadLog
	}

	return true, []string{
		desFile,
	}
}

func (op *AgentOsOperator) loadDockerImageFromGzip(funcArgs []string) (bool, []string) {
	gzipImageFromFullName := funcArgs[2]

	if !BasicFileExistAndNotNull(LocalGzipImageFolderPrefix + gzipImageFromFullName) {
		return false, []string{
			LocalGzipImageFolderPrefix + gzipImageFromFullName,
			"local gzip file not exits!",
		}
	}

	hardCodeCommand := "docker load < " + LocalGzipImageFolderPrefix + gzipImageFromFullName
	executor, i := HardCodeCommandExecutor(hardCodeCommand)
	if !executor {
		return false, i
	}

	if !BasicDockerImageExistByFullName(funcArgs[0]) {
		return false, []string{
			"docker load from gzip file error ! image not exits!",
			funcArgs[0],
		}
	}

	return true, nil
}
func (op *AgentOsOperator) pushImageToTargetHarbor(funcArgs []string) (bool, []string) {

	targetHarborHost := funcArgs[5]
	imageFullName := funcArgs[0]

	if !strings.Contains(targetHarborHost, "8033") {
		targetHarborHost += ":8033"
	}

	targetImageFullName := image.ImageNameToTargetImageFullName(imageFullName, targetHarborHost)

	if !PureResultSingleExecute([]string{
		"docker",
		"tag",
		imageFullName,
		targetImageFullName,
	}) {
		return false, []string{
			"docker tag error!",
		}
	}
	if strings.HasPrefix(targetImageFullName, image.CmiiHarborPrefix) {
		HardCodeCommandExecutor("docker login -u rad02_drone -p Drone@1234 harbor.cdcyy.com.cn")
	} else {
		HardCodeCommandExecutor("docker login -u admin -p V2ryStr@ngPss " + targetHarborHost)
	}

	ok, resultLog := AllCommandExecutor([]string{
		"docker",
		"push",
		targetImageFullName,
	})
	if !ok {
		return false, resultLog
	}

	return true, []string{
		targetImageFullName,
	}
}

func (op *AgentOsOperator) updateImageTag(funcArgs []string) (bool, []string) {
	namespace := funcArgs[6]
	imageFullName := funcArgs[0]
	if !strings.HasPrefix(imageFullName, image.CmiiHarborPrefix) {
		return false, []string{
			"cant update this image !",
		}
	}
	appName := image.ImageFullNameToAppName(imageFullName)
	newTag := image.ImageFullNameToImageTag(imageFullName)

	sprintf := fmt.Sprintf("start to update [%s] image tag [%s] to [%s]", namespace, appName, newTag)
	log.Info(sprintf)

	update, resultLog := K8sDeploymentUpdateTag(namespace, appName, newTag)
	if !update {
		return false, []string{
			sprintf,
		}
	}
	return true, []string{
		resultLog,
	}
}

func (op *AgentOsOperator) updateImageTagByFile(funcArgs []string) (bool, []string) {
	namespace := funcArgs[6]
	//targetImageFullName := funcArgs[7]
	proxyUrl := funcArgs[4]
	if !BasicCommandExistByPath("kubectl") {
		return false, []string{
			"kubectl not exits !",
		}
	}
	imageFullName := funcArgs[0]
	if !strings.HasPrefix(imageFullName, image.CmiiHarborPrefix) {
		return false, []string{
			"cant update this image !",
		}
	}
	appName := image.ImageFullNameToAppName(imageFullName)

	// 2024年4月7日 修改为 exec file的模式
	folderPrefix := "/root/wdd/update/"
	BasicCreateFolder(folderPrefix)

	updateFileName := "update-app-tag.sh"
	if !BasicFileExistAndNotNull(folderPrefix + updateFileName) {
		// kubectl update tag file not exits!
		download, downloadLog := BasicDownloadFile(AgentOsOperatorCache.OssOfflinePrefix+updateFileName, proxyUrl, DefaultSocks5ProxyUser, DefaultSocks5ProxyPass, folderPrefix+updateFileName)

		if !download {
			return false, downloadLog
		}
	}

	PureResultSingleExecute([]string{
		"chomd",
		"+x",
		folderPrefix + updateFileName,
	})

	newTag := image.ImageFullNameToImageTag(imageFullName)
	log.InfoF("start do update %s %s to %s", namespace, appName, newTag)
	updateCommand := "bash " + folderPrefix + updateFileName + namespace + appName + newTag
	executor, i := HardCodeCommandExecutor(updateCommand)
	if !executor {
		return false, i
	}

	return true, i
}
