package cm

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"ems.agt/lib/dborm"
	"ems.agt/lib/log"
	"ems.agt/lib/services"
	"ems.agt/restagent/config"

	"github.com/gorilla/mux"
)

var (
	// General License URI
	UriLicense    = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/license"
	UriLicenseExt = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/license"

	CustomUriLicense    = config.UriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/license"
	CustomUriLicenseExt = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/license"
)

func UploadLicenseFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("UploadLicenseFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Http request error:", err)
		return
	}

	vars := mux.Vars(r)
	neType := vars["neType"]
	if neType == "" {
		log.Error("neType is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	// neTypeUpper := strings.ToUpper(neType)
	// neTypeLower := strings.ToLower(neType)

	services.ResponseStatusOK204NoContent(w)
}

func DownloadLicenseFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("DownloadLicenseFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Request error:", err)
		return
	}

	vars := mux.Vars(r)
	neType := vars["neType"]
	if neType == "" {
		log.Error("neType is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	// // neTypeUpper := strings.ToUpper(neType)
	// //neTypeLower := strings.ToLower(neType)

	// version := vars["version"]
	// if version == "" {
	// 	log.Error("version is empty")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }

	// sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version)
	// neSoftware, err := dborm.XormGetDataBySQL(sql)
	// if err != nil {
	// 	log.Error("Faile to XormGetDataBySQL:", err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// } else if len(*neSoftware) == 0 {
	// 	err := global.ErrCMNotFoundTargetSoftware
	// 	log.Error(err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// }

	// fileName := (*neSoftware)[0]["file_name"]
	// path := (*neSoftware)[0]["path"]
	// md5Sum := (*neSoftware)[0]["md5_sum"]

	// services.ResponseFileWithNameAndMD5(w, http.StatusOK, fileName, path, md5Sum)
}

func DeleteLcenseFile(w http.ResponseWriter, r *http.Request) {
	log.Debug("DeleteLcenseFile processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Request error:", err)
		return
	}

	vars := mux.Vars(r)
	neType := vars["neType"]
	if neType == "" {
		log.Error("neType is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	// neTypeUpper := strings.ToUpper(neType)
	// //neTypeLower := strings.ToLower(neType)

	// version := vars["version"]
	// if version == "" {
	// 	log.Error("version is empty")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }

	// sql := fmt.Sprintf("select * from ne_software where ne_type='%s' and version='%s'", neTypeUpper, version)
	// neSoftware, err := dborm.XormGetDataBySQL(sql)
	// if err != nil {
	// 	log.Error("Faile to XormGetDataBySQL:", err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// } else if len(*neSoftware) == 0 {
	// 	err := global.ErrCMNotFoundTargetSoftware
	// 	log.Error(err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// }

	// where := fmt.Sprintf("ne_type='%s' and version='%s'", neTypeUpper, version)
	// affected, err := dborm.XormDeleteDataByWhere(where, "ne_software")
	// if err != nil || affected == 0 {
	// 	log.Error("Faile to XormGetDataBySQL:", err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// }

	// fileName := (*neSoftware)[0]["file_name"]
	// path := (*neSoftware)[0]["path"]
	// filePath := fmt.Sprintf("%s/%s", path, fileName)
	// err = os.Remove(filePath)
	// if err != nil {
	// 	log.Error("Faile to Remove:", err)
	// 	services.ResponseInternalServerError500ProcessError(w, err)
	// 	return
	// }

	services.ResponseStatusOK204NoContent(w)
}

func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
	log.Info("UploadLicenseFileData processing... ")

	_, err := services.CheckFrontValidRequest(w, r)
	if err != nil {
		log.Error("Http request error:", err)
		return
	}

	vars := mux.Vars(r)
	neType := vars["elementTypeValue"]
	if neType == "" {
		log.Error("elementTypeValue is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	neTypeUpper := strings.ToUpper(neType)
	neTypeLower := strings.ToLower(neType)

	//md5Param := services.GetUriParamString(r, "md5Sum", ",", false, false)

	neId := services.GetUriParamString(r, "neId", ",", false, false)

	neInfo, err := dborm.XormGetNeInfo(neType, neId)
	if err != nil {
		log.Errorf("Failed to get ne_info:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}
	log.Debug("neInfo:", neInfo)

	licensePath := fmt.Sprintf("%s/%s", config.GetYamlConfig().OMC.License, neTypeLower)
	err = os.MkdirAll(licensePath, os.ModePerm)
	if err != nil {
		log.Error("Failed to Mkdir:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}
	//fileName, err := services.HandleUploadFile(r, softwarePath, "")

	// 解析multipart/form-data请求
	err = r.ParseMultipartForm(10 << 20) // 10MB
	if err != nil {
		log.Error("Faile to ParseMultipartForm:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	// 获取文件和数据
	licFile := r.MultipartForm.File["file"]
	data := r.MultipartForm.Value["comment"]

	var licenseFileName, comment string

	// 处理软件rpm/deb文件
	if len(licFile) > 0 {
		file := licFile[0]
		// 打开文件
		f, err := file.Open()
		if err != nil {
			log.Error("Faile to Open:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
		defer f.Close()

		// 创建本地文件
		dst, err := os.Create(licensePath + "/" + file.Filename)
		if err != nil {
			log.Error("Faile to Create:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
		defer dst.Close()

		licenseFileName = file.Filename
		// 将文件内容拷贝到本地文件
		_, err = io.Copy(dst, f)
		if err != nil {
			log.Error("Faile to Copy:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	}

	// 处理数据
	if len(data) > 0 {
		comment = data[0]
	}

	neLicensePath := strings.ReplaceAll(config.GetYamlConfig().NE.LicenseDir, "{neType}", neTypeLower)

	srcFile := fmt.Sprintf("%s/%s", licensePath, licenseFileName)
	scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User, neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
	cmd := exec.Command("scp", "-r", srcFile, scpDir)
	out, err := cmd.CombinedOutput()
	log.Debugf("Exec output: %v", string(out))
	if err != nil {
		log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}
	// backup system.ini to system.ini.bak
	sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
	cpCmd := fmt.Sprintf("sudo cp -f %s/system.ini %s/system.ini.bak", neLicensePath, neLicensePath)
	cmd = exec.Command("ssh", sshHost, cpCmd)
	out, err = cmd.CombinedOutput()
	log.Debugf("Exec output: %v", string(out))
	if err != nil {
		log.Error("Faile to execute cp command:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	// replace system.ini
	neFilePath := config.GetYamlConfig().NE.ScpDir + "/" + licenseFileName
	cpCmd = fmt.Sprintf("sudo mv -f %s %s/system.ini", neFilePath, neLicensePath)
	cmd = exec.Command("ssh", sshHost, cpCmd)
	out, err = cmd.CombinedOutput()
	log.Debugf("Exec output: %v", string(out))
	if err != nil {
		log.Error("Faile to execute cp command:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	switch neTypeLower {
	case "omc":
		restartCmd := fmt.Sprintf("sudo %s/bin/omcsvc.sh restart", config.GetYamlConfig().NE.OmcDir)
		cmd := exec.Command("ssh", sshHost, restartCmd)
		out, err := cmd.CombinedOutput()
		log.Debugf("Exec output: %v", string(out))
		if err != nil {
			log.Error("Faile to execute ssh restart omc:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	case "ims":
		restartCmd := "sudo ims-stop && sudo ims-start"
		cmd := exec.Command("ssh", sshHost, restartCmd)
		out, err := cmd.CombinedOutput()
		log.Debugf("Exec output: %v", string(out))
		if err != nil {
			log.Error("Faile to execute ssh sudo systemctl command:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	default:
		restartCmd := fmt.Sprintf("sudo systemctl restart %s.service", neTypeLower)
		cmd := exec.Command("ssh", sshHost, restartCmd)
		out, err := cmd.CombinedOutput()
		log.Debugf("Exec output: %v", string(out))
		if err != nil {
			log.Error("Faile to execute ssh sudo systemctl command:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		}
	}

	neLicense := dborm.NeLicense{
		NeType:   neTypeUpper,
		NeID:     neId,
		Status:   "ACTIVE",
		Path:     licensePath,
		FileName: licenseFileName,
		Comment:  comment,
	}

	log.Debug("neLicense:", neLicense)
	_, err = dborm.XormInsertTableOne("ne_license", neLicense)
	if err != nil {
		log.Error("Faile to XormInsertTableOne:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	services.ResponseStatusOK204NoContent(w)
}
