package event

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"be.ems/lib/core/ctx"
	"be.ems/lib/dborm"
	"be.ems/lib/global"
	"be.ems/lib/log"
	"be.ems/lib/services"
	"be.ems/restagent/config"
	neService "be.ems/src/modules/network_element/service"
	wsService "be.ems/src/modules/ws/service"
	"github.com/gin-gonic/gin"
)

var (
	// 走Gin
	UriUEEventAMF = "/upload-ue/v1/:eventType"
	// 走Mux
	UriUEEvent       = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
	CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
)

type UEEvent struct {
	NeType    string         `json:"neType" xorm:"ne_type"`
	NeName    string         `json:"neName" xorm:"ne_name"`
	RmUID     string         `json:"rmUID" xorm:"rm_uid"`
	Timestamp int64          `json:"timestamp" xorm:"timestamp"`
	EventType string         `json:"eventType" xorm:"event_type"`
	EventJson map[string]any `json:"eventJSON" xorm:"event_json"`
}

func PostUEEventFromAMF(c *gin.Context) {
	log.Info("PostUEEventFromAMF processing... ")

	body, err := io.ReadAll(io.LimitReader(c.Request.Body, global.RequestBodyMaxLen))
	if err != nil {
		log.Error("Failed to io.ReadAll: ", err)
		services.ResponseNotFound404UriNotExist(c.Writer, c.Request)
		return
	}

	//vars := mux.Vars(c.Request)
	eventType, ok := c.Params.Get("eventType")
	if !ok || eventType == "" {
		log.Error("eventType is empty")
		services.ResponseNotFound404UriNotExist(c.Writer, c.Request)
		return
	}
	ueEvent := new(UEEvent)
	err = json.Unmarshal(body, &ueEvent.EventJson)
	if err != nil {
		log.Error("Failed to Unmarshal ueEvent:", err)
		services.ResponseInternalServerError500ProcessError(c.Writer, err)
		return
	}
	ueEvent.NeType = "AMF"
	ueEvent.Timestamp = time.Now().Unix()
	ueEvent.EventType = eventType
	log.Trace("ueEvent AMF:", ueEvent)

	affected, err := dborm.XormInsertTableOne("ue_event_amf", ueEvent)
	if err != nil && affected <= 0 {
		log.Error("Failed to insert ue_event_amf:", err)
		services.ResponseInternalServerError500ProcessError(c.Writer, err)
		return
	}

	// AMF没有RmUID，直接推送
	// 推送到ws订阅组
	wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent)

	services.ResponseStatusOK204NoContent(c.Writer)
}

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

	neType := ctx.GetParam(r, "elementTypeValue")
	var ueEvent UEEvent
	if err := ctx.ShouldBindJSON(r, &ueEvent); err != nil {
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	ueEvent.NeType = strings.ToUpper(neType)
	tableName := fmt.Sprintf("ue_event_%s", strings.ToLower(neType))
	affected, err := dborm.XormInsertTableOne(tableName, ueEvent)
	if err != nil && affected <= 0 {
		log.Error("Failed to insert "+tableName, err)
		services.ResponseInternalServerError500ProcessError(w, err)
		return
	}

	// 发送到匹配的网元
	neInfo := neService.NewNeInfo.SelectNeInfoByRmuid(ueEvent.RmUID)
	if neInfo.RmUID == ueEvent.RmUID {
		// 推送到ws订阅组
		if ueEvent.NeType == "MME" {
			wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+neInfo.NeId, ueEvent)
		}
	}

	services.ResponseStatusOK204NoContent(w)
}
