package cm

import (
	"strings"

	"be.ems/lib/config"
	"be.ems/lib/core/ctx"
	"be.ems/lib/global"
	"be.ems/lib/log"
	"be.ems/lib/services"

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

	neService "be.ems/src/modules/network_element/service"

	"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... ")

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

	neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)

	var response services.DataResponse
	if neInfo.NeId == neId && neInfo.NeId != "" {
		requestURI2NF := fmt.Sprintf("http://%s:%v%s", neInfo.IP, neInfo.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... ")

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

	neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)

	if neInfo.NeId != neId || neInfo.NeId == "" {
		log.Error("neId is empty")
		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... ")

	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 := ctx.GetQuery(r, "ne_id")
	neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)

	if neInfo.NeId != neId || neInfo.NeId == "" {
		log.Error("neId is empty")
		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) {
	services.ResponseStatusOK204NoContent(w)
}

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

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

	neId := ctx.GetQuery(r, "ne_id")
	neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neType, neId)

	if neInfo.NeId != neId || neInfo.NeId == "" {
		log.Error("neId is empty")
		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)
}
