package controllers

import (
	"crypto/tls"
	"encoding/json"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"k8s-console/dto"
	"k8s-console/models"
	"k8s-console/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"net/http"
	"strings"
	"time"
)

// CommonController operations for common
type CommonController struct {
	beego.Controller
}

var (
	infoLogger  = logs.GetLogger("info")
	errorLogger = logs.GetLogger("error")
	//当前命名空间
	nameSpace = beego.AppConfig.String("nameSpace")
)

// URLMapping ...
func (c *CommonController) URLMapping() {
	c.Mapping("getUserAllNameSpaces", c.GetUserAllNameSpaces)
	c.Mapping("getControllerNameListByNameSpace", c.GetControllerNameListByNameSpace)
}

// Post ...
// @Title GetUserAllNameSpaces
// @Description get UserAllNameSpaces
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	dto.GetUserAllNameSpaceRequestDto	true	""
// @Success 200 {object} dto.BaseResultResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /getUserAllNameSpaces [post]
func (c *CommonController) GetUserAllNameSpaces() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto dto.GetUserAllNameSpaceRequestDto
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	successResponseDto.Status = 200
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestDto); err != nil {
		errorLogger.Println(err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	userId := requestDto.UserId
	if userId <= 0 {
		errorLogger.Println("用户id必须大于0")
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	//获取泛域名
	_, _, appExtensiveDomain, err := models.GetHarborIngressAndPwd("harbor", true)
	if err != nil {
		errorLogger.Println("获取集群泛域名失败:", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
		Timeout: 10 * time.Second,
	}

	// 调用租户客户端接口查询当前用户所有命名空间
	tenantManageClientUrl := beego.AppConfig.String("tenantManageClientUrl") + "." + appExtensiveDomain
	url := tenantManageClientUrl + "/v1/tenant_namespace/getUserAllNameSpace?lang=" + lang

	requestMap := map[string]int{
		"userId": userId,
	}
	//map转json
	params, _ := json.Marshal(requestMap)

	infoLogger.Printf("调用租户客户端查询当前用户所有命名空间接口请求地址: %s 参数: %s", url, string(params))
	req, _ := http.NewRequest("POST", url, strings.NewReader(string(params)))
	req.Header.Set("Content-Type", "application/json;charset=utf-8")

	res, err := httpClient.Do(req)
	if err != nil {
		errorLogger.Printf("调用租户客户端查询当前用户所有命名空间接口失败:%s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang,
			"getUserAllNameSpaces_callInterfaceToGetUserAllNameSpacesFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	resByte, err := ioutil.ReadAll(res.Body)
	if err != nil {
		errorLogger.Printf("解析调用租户客户端查询当前用户所有命名空间接口返回参数失败:%s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang,
			"getUserAllNameSpaces_parseCallInterfaceToGetUserAllNameSpacesResultFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	infoLogger.Printf("调用租户客户端查询当前用户所有命名空间接口返回值:%s", string(resByte))
	m := map[string]interface{}{}
	if err := json.Unmarshal(resByte, &m); err != nil {
		errorLogger.Printf("解析调用租户客户端查询当前用户所有命名空间接口返回参数失败:%s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang,
			"getUserAllNameSpaces_parseCallInterfaceToGetUserAllNameSpacesResultFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if int(m["responseCode"].(float64)) == 300 {
		errorResponseDto.Message = m["Message"].(string)
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	successResponseDto.Result = m["result"].([]interface{})
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

/**
  获取租户环境，harbor地址， 密码，泛域名接口
*/
// @router / [post]
func (c *CommonController) GetClusterConfigInfo() {
	//	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang("", "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	successResponseDto.Status = 200
	infoBean, e := models.GetClusterConfigInfoData("harbor")
	if e != nil {
		successResponseDto.Result = infoBean
		successResponseDto.Status = 300
		c.Data["json"] = successResponseDto
		c.ServeJSON()
		return
	}
	successResponseDto.Result = infoBean
	successResponseDto.Status = 200
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

// 执行校验license是否失效
func VerifyLicenseValid(lang string) dto.BaseResponseDto {
	var responseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		responseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		return responseDto
	}

	//查询configMap里面的license信息
	configMap, err := k8sClient.CoreV1().ConfigMaps("default").
		Get("clusterconfig-configmap", metav1.GetOptions{})
	if err != nil {
		errorLogger.Printf("查询default空间名称为clusterconfig-configmap的configMap的license信息失败: %s",
			err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "verifyLicenseValid_queryLicenseInfoFail")
		return responseDto
	}
	if _, ok := configMap.Data["license_str"]; !ok {
		errorLogger.Println("default空间名称为clusterconfig-configmap的configMap未存储license信息")
		responseDto.Message = utils.GetI18nLang(lang, "verifyLicenseValid_notFoundLicenseInfo")
		return responseDto
	}
	licenseInfo := configMap.Data["license_str"]

	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}

	tenantManage_server_url := beego.AppConfig.String("tenantManage_server_url")
	url := tenantManage_server_url + "/v1/tenant_license/isValidLicense/" + string(licenseInfo)
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Content-Type", "application/json;charset=utf-8")

	res, err := httpClient.Do(req)
	if err != nil {
		errorLogger.Printf("调用检查License是否失效接口失败:%s", err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "verifyLicenseValid_callInterfaceToVerifyLicenseValidFail")
		return responseDto
	}

	resByte, err := ioutil.ReadAll(res.Body)
	if err != nil {
		errorLogger.Printf("解析调用检查License是否失效接口返回参数失败:%s", err.Error())
		responseDto.Message = utils.GetI18nLang(lang,
			"verifyLicenseValid_parseCallInterfaceToVerifyLicenseValidResultFail")
		return responseDto
	}
	infoLogger.Println(string(resByte))

	m := map[string]interface{}{}
	if err := json.Unmarshal(resByte, &m); err != nil {
		errorLogger.Printf("解析调用检查License是否失效接口返回参数失败:%s", err.Error())
		responseDto.Message = utils.GetI18nLang(lang,
			"verifyLicenseValid_parseCallInterfaceToVerifyLicenseValidResultFail")
		return responseDto
	}
	infoLogger.Printf("调用检查License是否失效接口返回值:%s", string(resByte))
	if int(m["ResponseCode"].(float64)) == 300 {
		responseDto.Message = m["Message"].(string)
		return responseDto
	}

	responseDto.Status = 200
	responseDto.Message = utils.GetI18nLang(lang, "success")
	return responseDto
}

// @router /getTemplate [get]
func (c *CommonController) GetKindTemplateInfo() {
	// ingress ,service ,deploy
	kindType := c.GetString("type")
	lang := c.GetString("lang")
	logs.Info("获取模板参数：", kindType, "--", lang)
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	successResponseDto.Status = 200
	result, e := models.GetKindTemplateInfo(kindType)
	if e != nil {
		logs.Error(e.Error())
		errorResponseDto.Status = 300
		errorResponseDto.Message = utils.GetI18nLang(lang, "getTemplateFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	//转换yaml格式
	yamlBytes, err := yaml.Marshal(result)
	if err != nil {
		logs.Error(err.Error())
		errorResponseDto.Status = 300
		errorResponseDto.Message = utils.GetI18nLang(lang, "getTemplateFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	successResponseDto.Result = string(yamlBytes)
	successResponseDto.Status = 200
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

// Post ...
// @Title GetControllerNameListByNameSpace
// @Description get ControllerNameListByNameSpace
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	dto.GetControllerNameListByNameSpaceRequestDto	true	""
// @Success 200 {object} dto.BaseResultResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /getControllerNameListByNameSpace [post]
func (c *CommonController) GetControllerNameListByNameSpace() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto dto.GetControllerNameListByNameSpaceRequestDto
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	successResponseDto.Status = 200
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestDto); err != nil {
		errorLogger.Println(err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	infoLogger.Printf("查询命名空间下的所有的%s请求参数: %v", requestDto.ControllerTypeName, requestDto)

	nameSpace := requestDto.NameSpace
	controllerTypeName := requestDto.ControllerTypeName
	//查询集群所有命名空间信息
	allNameSpaceList, err := utils.GetClusterAllNameSpaces(lang)
	infoLogger.Println(allNameSpaceList)
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "getClusterAllNamespacesFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, nameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		errorResponseDto.Message = utils.GetI18nLang(lang, "theNameSpaceNotExistInCluster")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if strings.TrimSpace(controllerTypeName) == "" || !utils.IsContains([]string{"deploy", "sts"}, controllerTypeName) {
		errorLogger.Println("控制器名称必须为deploy或sts")
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		errorResponseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	result := []string{}
	if controllerTypeName == "deploy" {
		//查询命名空间下所有deployment信息
		deploymentList, err := k8sClient.AppsV1().Deployments(nameSpace).List(metav1.ListOptions{})
		if err != nil {
			errorLogger.Printf("查询集群%s空间所有deployment失败: %s", nameSpace, err.Error())
			errorResponseDto.Message = utils.GetI18nLang(lang, "getDeploymentListByNameSpaceFail")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		for _, item := range deploymentList.Items {
			infoLogger.Println("deploy名称:", item.Name)
			result = append(result, item.Name)
		}
		infoLogger.Printf("所有deploy名称: %v", result)
	} else if controllerTypeName == "sts" {
		//查询命名空间下所有StatefulSet信息
		statefulSetList, err := k8sClient.AppsV1().StatefulSets(nameSpace).List(metav1.ListOptions{})
		if err != nil {
			errorLogger.Printf("查询集群%s空间所有StatefulSet失败: %s", nameSpace, err.Error())
			errorResponseDto.Message = utils.GetI18nLang(lang,
				"getControllerNameListByNameSpace_getNamespaceAllStatefulSetFail")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		for _, item := range statefulSetList.Items {
			infoLogger.Println("StatefulSet名称:", item.Name)
			result = append(result, item.Name)
		}
		infoLogger.Printf("所有StatefulSet名称: %v", result)
	}

	successResponseDto.Result = result
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}
