package cmii_operator

import (
	"errors"
	"os"
	"strings"
	"wdd.io/agent-go/executor"
	"wdd.io/agent-go/utils"
	"wdd.io/cmii_operator/image"
)

const OfflineImageGzipFolderPrefix = "/root/octopus_image/"
const OfflineDeployHarborHost = "harbor.wdd.io"
const PublicDeployHarborHost = "42.192.52.227"
const DirectPushDeployHarborHost = "36.134.28.60"

func FetchDemoImages(projectName string, gzipSplit bool) (errorPullImageList, errorGzipImageList []string) {

	// generate a project folder
	err := os.MkdirAll(OfflineImageGzipFolderPrefix+projectName, os.ModeDir)
	if err != nil {
		if !errors.Is(err, os.ErrExist) {
			log.ErrorF("[FetchDemoImages] - create folder of %s error %s", OfflineImageGzipFolderPrefix+projectName, err.Error())
			return errorPullImageList, errorGzipImageList
		}
	}

	// get demo image version map
	backendMap, frontendMap, srsMap := BackupAllCmiiDeploymentToMap(demo)

	utils.BeautifulPrint(backendMap)
	utils.BeautifulPrint(frontendMap)
	utils.BeautifulPrint(srsMap)

	// save map to file
	backendMapFile := OfflineImageGzipFolderPrefix + projectName + "-backend-app.json"
	frontendMapFile := OfflineImageGzipFolderPrefix + projectName + "-frontend-app.json"
	srsMapFile := OfflineImageGzipFolderPrefix + projectName + "-srs-app.json"
	_ = os.Remove(backendMapFile)
	_ = os.Remove(frontendMapFile)
	_ = os.Remove(srsMapFile)

	executor.BasicAppendContentToFile(
		utils.BeautifulPrintToString(backendMap),
		backendMapFile,
	)
	executor.BasicAppendContentToFile(
		utils.BeautifulPrintToString(frontendMap),
		frontendMapFile,
	)
	executor.BasicAppendContentToFile(
		utils.BeautifulPrintToString(srsMapFile),
		srsMapFile,
	)

	// download image
	backendPull := image.ImagePullFromCmiiHarborByMap(backendMap, true)
	frontendPull := image.ImagePullFromCmiiHarborByMap(frontendMap, true)
	srsPull := image.ImagePullFromCmiiHarborByMap(srsMap, true)

	// compress image
	if gzipSplit {
		for image_name, tag := range backendMap {
			if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
				errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
			}
		}
		for image_name, tag := range frontendMap {
			if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
				errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
			}
		}
		for image_name, tag := range srsMap {
			if !image.SaveToTarGZ(image_name+":"+tag, OfflineImageGzipFolderPrefix+projectName+"/app/") {
				errorGzipImageList = append(errorGzipImageList, image.CmiiHarborPrefix+image_name+":"+tag)
			}
		}
	}
	// upload to harbor

	// clean up images

	errorPullImageList = append(errorPullImageList, backendPull...)
	errorPullImageList = append(errorPullImageList, frontendPull...)
	errorPullImageList = append(errorPullImageList, srsPull...)

	return errorPullImageList, errorGzipImageList
}

func FetchVersionImages(cmiiVersion string, gzipSplit bool) (errorPullImageList, errorGzipImageList []string) {

	// generate a project folder
	err := os.MkdirAll(OfflineImageGzipFolderPrefix+cmiiVersion, os.ModeDir)
	if err != nil {
		if !errors.Is(err, os.ErrExist) {
			log.ErrorF("[FetchDemoImages] - create folder of %s error %s", OfflineImageGzipFolderPrefix+cmiiVersion, err.Error())
			return errorPullImageList, errorGzipImageList
		}
	}

	backendMap := CmiiBackendAppMap
	frontendMap := CmiiFrontendAppMap

	for app, _ := range backendMap {
		backendMap[app] = cmiiVersion
	}
	for app, _ := range frontendMap {
		frontendMap[app] = cmiiVersion
	}

	var allCmiiImageName []string

	allCmiiImageName = append(allCmiiImageName, image.ConvertCMiiImageMapToList(backendMap)...)
	allCmiiImageName = append(allCmiiImageName, image.ConvertCMiiImageMapToList(frontendMap)...)

	for key, value := range CmiiSrsAppMap {
		var app *CmiiDeploymentInterface
		if strings.Contains(value, "deployment") {
			app = CmiiOperator.DeploymentOneInterface(demo, key)
			if app != nil {
				allCmiiImageName = append(allCmiiImageName, app.Image)
			}
		} else if strings.Contains(value, "state") {
			app = CmiiOperator.StatefulSetOneInterface(demo, key)
			if app != nil {
				for _, imageName := range app.ContainerImageMap {
					allCmiiImageName = append(allCmiiImageName, imageName)
				}
			}
		}
	}

	utils.BeautifulPrint(allCmiiImageName)

	// do work
	errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(allCmiiImageName, OfflineImageGzipFolderPrefix+cmiiVersion)

	return errorPullImageList, errorGzipImageList
}

func FetchDependencyRepos(gzipSplit bool) (errorPullImageList, errorGzipImageList []string) {
	err := os.MkdirAll(OfflineImageGzipFolderPrefix, os.ModeDir)
	if err != nil {
		if !errors.Is(err, os.ErrExist) {
			log.ErrorF("[FetchDependencyRepos] - create folder of %s error %s", OfflineImageGzipFolderPrefix, err.Error())
		}
	}

	errorPullImageList, errorGzipImageList = image.PullFromListAndCompressSplit(image.MiddlewareAmd64, OfflineImageGzipFolderPrefix+"middle/")

	pull, gzipImageList := image.PullFromListAndCompressSplit(image.Rancher1204Amd64, OfflineImageGzipFolderPrefix+"rke/")

	return append(errorPullImageList, pull...), append(errorGzipImageList, gzipImageList...)

}

func LoadSplitGzipImageToTargetHarbor(projectName, targetHarborHost string) (errorLoadImageNameList, errorPushImageNameList []string) {

	// list folder
	projectGzipFolder := OfflineImageGzipFolderPrefix + projectName
	errorLoadImageNameList = append(errorLoadImageNameList, image.ImageLoadFromFolderPath(projectGzipFolder)...)
	// read from json
	errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Cmii520DemoImageList, targetHarborHost)...)

	// re-tag
	// push

	// todo clean host and harbor
	// check harbor exits

	return errorLoadImageNameList, errorPushImageNameList
}

func LoadSplitDepGzipImageToTargetHarbor(targetHarborHost string) (errorLoadImageNameList []string, errorPushImageNameList []string) {

	//middle := OfflineImageGzipFolderPrefix + "middle/"
	//rke := OfflineImageGzipFolderPrefix + "rke/"
	//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(middle)...)
	//errorLoadImageNameList = append(errorLoadImageNameList, ImageLoadFromFolderPath(rke)...)

	errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.MiddlewareAmd64, targetHarborHost)...)
	errorPushImageNameList = append(errorPushImageNameList, image.TagFromListAndPushToCHarbor(image.Rancher1204Amd64, targetHarborHost)...)

	return errorLoadImageNameList, errorPushImageNameList

}
