package cm

import (
	"strings"

	"nms_nbi/lib/dborm"
	"nms_nbi/lib/global"
	"nms_nbi/lib/log"
	"nms_nbi/lib/services"
	"nms_nbi/restagent/config"

	"encoding/json"
	"fmt"
	"io"
	"net/http"

	tokenConst "nms_nbi/src/framework/constants/token"

	"github.com/go-resty/resty/v2"
	"github.com/gorilla/mux"
)

var (
	// parameter config management
	ParamConfigUri = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"

	CustomParamConfigUri = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/config/{paraName}"
)

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

	//	data := make([]map[string]interface{}, 1)
	var response services.DataResponse
	vars := mux.Vars(r)
	neType := vars["elementTypeValue"]
	if neType == "" {
		log.Error("elementTypeValue is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

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

	restHostPort := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
	getNeInfoPattern := fmt.Sprintf(config.DefaultUriPrefix+"/databaseManagement/v1/%s/ne_info", config.GetYamlConfig().Database.Name)
	getNeInfoURI := restHostPort + getNeInfoPattern
	neId := services.GetUriParamString(r, "ne_id", ",", true, true)
	if neId == "" {
		getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status+in+('0','3')+and+ne_type='%s'", neType)
	} else {
		getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status+in+('0','3')+and+ne_type='%v'+and+ne_id+in+%v", neType, neId)
	}
	log.Debug("getNeInfoURI:", getNeInfoURI)

	client := resty.New()
	resp, err := client.R().
		EnableTrace().
		SetHeaders(map[string]string{tokenConst.HEADER_KEY: r.Header.Get(tokenConst.HEADER_KEY)}).
		SetHeaders(map[string]string{"accessToken": token}).
		SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
		SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
		Get(getNeInfoURI)
	if err != nil {
		log.Error("Failed to Get:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}
	log.Trace("NE info:", string(resp.Body()))

	//	var neList []dborm.NeInfo
	neList, _ := dborm.XormParseResult(resp.Body())

	if len(neList) >= 1 {
		s := neList[0]
		requestURI2NF := fmt.Sprintf("http://%s:%v%s", s.Ip, s.Port, r.RequestURI)
		log.Debug("requestURI2NF:", requestURI2NF)

		resp, err := client.R().
			EnableTrace().
			SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
			SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
			Get(requestURI2NF)
		if err != nil {
			log.Error("Failed to Get from NF:", err)
			services.ResponseInternalServerError500ProcessError(w, err)
			return
		} else {
			_ = json.Unmarshal(resp.Body(), &response)
		}
		log.Debug("response:", response)
	}

	services.ResponseWithJson(w, http.StatusOK, response)
}

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

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

	vars := mux.Vars(r)
	neType := vars["elementTypeValue"]
	if neType == "" {
		log.Error("elementTypeValue is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	neId := services.GetUriParamString(r, "ne_id", ",", false, false)

	//	no, _ := strconv.ParseInt(neId, 10, 64)
	neInfo, err := dborm.XormGetNeInfo(neType, neId)
	if err != nil {
		log.Error("dborm.XormGetNeInfo is failed:", err)
		services.ResponseInternalServerError500DatabaseOperationFailed(w)
		return
	}

	requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.Ip, neInfo.Port, r.RequestURI)
	log.Debug("requestURI2NF: POST ", requestURI2NF)

	body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
	if err != nil {
		log.Error("io.ReadAll is failed:", err)
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	client := resty.New()
	response, err := client.R().
		EnableTrace().
		SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
		SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
		SetBody(body).
		Post(requestURI2NF)
	if err != nil {
		log.Error("Failed to POST to NF:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	services.ResponseWithJson(w, http.StatusNoContent, response)
}

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

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

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

	// OMC配置接口 /api/rest/systemManagement/v1/elementType/omc/objectType/config/omcNeConfig
	if v, ok := vars["paraName"]; ok && v == "omcNeConfig" && strings.ToLower(neType) == "omc" {
		PutOMCNeConfig(w, r)
		return
	}

	neId := services.GetUriParamString(r, "ne_id", ",", false, false)
	//	no, _ := strconv.ParseInt(neId, 10, 64)
	neInfo, err := dborm.XormGetNeInfo(neType, neId)
	if err != nil {
		log.Error("dborm.XormGetNeInfo is failed:", err)
		services.ResponseInternalServerError500DatabaseOperationFailed(w)
		return
	}

	requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.Ip, neInfo.Port, r.RequestURI)
	log.Debug("requestURI2NF: PUT ", requestURI2NF)

	body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen)) //io.LimitReader限制大小
	if err != nil {
		log.Error("io.ReadAll is failed:", err)
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}

	client := resty.New()
	response, err := client.R().
		EnableTrace().
		SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
		SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
		SetBody(body).
		Put(requestURI2NF)
	if err != nil {
		log.Error("Failed to Put to NF:", err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	services.ResponseWithJson(w, http.StatusNoContent, response)
}

// PutOMCNeConfig 网元OMC配置
//
// 目前没配置，返回204
func PutOMCNeConfig(w http.ResponseWriter, r *http.Request) {
	// vars := mux.Vars(r)
	// neType := vars["elementTypeValue"]
	// if neType == "" {
	// 	log.Error("elementTypeValue is empty")
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }
	// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
	// if err != nil {
	// 	log.Error("Failed to io.ReadAll:", err)
	// 	services.ResponseNotFound404UriNotExist(w, r)
	// 	return
	// }

	// neInfo := new(dborm.NeInfo)
	// _ = json.Unmarshal(body, neInfo)
	// neInfo.NeType = strings.ToUpper(neType)

	services.ResponseStatusOK204NoContent(w)
}

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

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

	vars := mux.Vars(r)
	neType := vars["elementTypeValue"]
	if neType == "" {
		log.Error("elementTypeValue is empty")
		services.ResponseNotFound404UriNotExist(w, r)
		return
	}
	neId := services.GetUriParamString(r, "ne_id", ",", false, false)

	//	no, _ := strconv.ParseInt(neId, 10, 64)
	neInfo, err := dborm.XormGetNeInfo(neType, neId)
	if err != nil {
		log.Error("dborm.XormGetNeInfo is failed:", err)
		services.ResponseInternalServerError500DatabaseOperationFailed(w)
		return
	}

	requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.Ip, neInfo.Port, r.RequestURI)
	log.Debug("requestURI2NF: DELETE ", requestURI2NF)

	client := resty.New()
	response, err := client.R().
		EnableTrace().
		SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
		SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
		Delete(requestURI2NF)
	if err != nil {
		log.Error("Failed to delete parameter:", err)
		services.ResponseInternalServerError500NFConnectRefused(w)
		return
	}

	services.ResponseWithJson(w, http.StatusNoContent, response)
}
