package event

import (
	"encoding/json"
	"fleetmanager/api/model/event"
	"fleetmanager/api/service/constants"
	"fleetmanager/client"
	"fleetmanager/db/dao"
	"fleetmanager/logger"
	"fleetmanager/utils"
	"fmt"
	"net/http"
	"strings"
)

const (
	EventResourceTypeUser     = "user"
	EventResourceTypeFleet    = "fleet"
	EventResourceTypeBuild    = "build"
	EventResourceTypeInstance = "instance"
	EventResourceTypeProcess  = "process"
	EventResourceTypeSession  = "session"
	EventResourceTypeRequest  = "request"

	EventResourceTraceService = "fleetmanager"
	EventTraceStateNormal     = "NORMAL"
	EventTraceStateWarning    = "WARNING"
	EventTraceStateIncident   = "INCIDENT"
	EventTypeData             = "data"
	EventTypeManager          = "manager"

	EventSmnMessagePattern = "Have triggerred an event: " +
		"Name: %s; ResourceType: %s; TraceService: %s; TraceState: %s. " +
		"More details can get from console."
)

type EventService struct {
	projectId string
	Logger    *logger.FMLogger
}

func NewEventService(projectId string, logger *logger.FMLogger) *EventService {
	return &EventService{
		projectId: projectId,
		Logger:    logger,
	}
}

func (s *EventService) RegisterEvent(registerReq *event.RegisterEventRequest) {
	s.Logger.Info("[register event] receive an event register request %s", registerReq.Name)
	u, err := dao.GetUserResConfByOriProjectId(s.projectId)
	if err != nil {
		s.Logger.Error("[register event] get res project id and region by ori project id %s error", s.projectId)
		return
	}
	url := client.GetServiceEndpoint(client.ServiceNameAASS, u.Region) + fmt.Sprintf(constants.AASSCreateOrListEventUrlPattern, u.OriProjectId)
	body, err := json.Marshal(registerReq)
	if err != nil {
		s.Logger.Error("[register event] marshal req %+v err %+v", registerReq, err)
		return
	}
	req := client.NewRequest(client.ServiceNameAASS, url, http.MethodPost, body)
	code, rsp, err := req.DoRequest()
	if err != nil {
		s.Logger.Error("[register event] register event %s err %+v", registerReq.Name, err)
		return
	}
	if code != http.StatusOK {
		s.Logger.Error("[register event] register event %s err because code is %d, rsp: %s", registerReq.Name, code, rsp)
		return
	}
	s.Logger.Info("[register event] success to register an event %s", registerReq.Name)
}

func (s *EventService) RegisterWorkflowEvent(name string, resId string, resName string, msg string) {
	registerReq := &event.RegisterEventRequest{
		Name:         name,
		ResourceType: strings.Split(name, "_")[1],
		TraceService: EventResourceTraceService,
		ResourceId:   resId,
		ResourceName: resName,
		TraceState:   EventTraceStateIncident,
		EventType:    EventTypeData,
		SourceIp:     utils.GetLocalIP(),
		Details:      msg,
	}
	registerReq.SmnMessage = fmt.Sprintf(EventSmnMessagePattern, name, registerReq.ResourceType,
		registerReq.TraceService, registerReq.TraceState)
	if registerReq.ResourceType == "build" {
		build, err := dao.GetBuildById(resId, s.projectId)
		if err == nil {
			registerReq.ResourceName = build.Name
		}
	} else if registerReq.ResourceType == "fleet" {
		fleet, err := dao.GetFleetStorage().Get(dao.Filters{"id": resId})
		if err == nil {
			registerReq.ResourceName = fleet.Name
		}
	}
	go s.RegisterEvent(registerReq)
}

func (s *EventService) RegisterWorkflowSuccessEvent(name string, resId string, resName string, msg string) {
	registerReq := &event.RegisterEventRequest{
		Name:         name,
		ResourceType: strings.Split(name, "_")[1],
		TraceService: EventResourceTraceService,
		ResourceId:   resId,
		ResourceName: resName,
		TraceState:   EventTraceStateNormal,
		EventType:    EventTypeData,
		SourceIp:     utils.GetLocalIP(),
		Details:      msg,
	}
	registerReq.SmnMessage = fmt.Sprintf(EventSmnMessagePattern, name, registerReq.ResourceType,
		registerReq.TraceService, registerReq.TraceState)
	if registerReq.ResourceType == "build" {
		build, err := dao.GetBuildById(resId, s.projectId)
		if err == nil {
			registerReq.ResourceName = build.Name
		}
	} else if registerReq.ResourceType == "fleet" {
		fleet, err := dao.GetFleetStorage().Get(dao.Filters{"id": resId})
		if err == nil {
			registerReq.ResourceName = fleet.Name
		}
	}
	go s.RegisterEvent(registerReq)
}