package engineer

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"go.uber.org/dig"

	engineerapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/ticket-manager/engineer"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver"
	apiutils "github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver/utils"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/errs"
	"github.com/tidbcloud/aisupport/services/ticket-manager/internal/app"
	engsvcapi "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/engineer/api"
)

type HandlerParam struct {
	dig.In

	Engineer engsvcapi.Service
}

type Handler struct {
	Engineer engsvcapi.Service
}

func NewEngineerHandler(param HandlerParam) app.HandlerResult {
	return app.HandlerResult{Handler: &Handler{Engineer: param.Engineer}}
}

func (h *Handler) Name() string {
	return "EngineerHandler"
}

func (h *Handler) Register(routers map[apiserver.RoutePath]gin.IRouter) error {
	router := routers[app.APIRoutePath]
	router.GET("/engineers", h.ListEngineers)
	router.GET("/engineers/:email", h.GetEngineer)
	router.POST("/engineers/sync", h.SyncEngineers)
	return nil
}

// ListEngineers lists engineers.
//
//	@Summary	List engineers
//	@Id			EngineerHandlerListEngineers
//	@Tags		EngineerHandler
//	@Accept		json
//	@Produce	json
//	@Param		param	query		engineerapi.ListEngineersRequest	false	"param"
//	@Success	200		{object}	engineerapi.ListEngineersResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/engineers [get]
func (h *Handler) ListEngineers(c *gin.Context) {
	var request engineerapi.ListEngineersRequest
	if err := c.ShouldBindQuery(&request); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	param := engsvcapi.ListEngineersParam{
		DispatchEnabledIs: request.Enabled,
		Keyword:           request.Keyword,
		Page: engsvcapi.PageParam{
			Page:     int(request.Page),
			PageSize: int(request.PageSize),
		},
	}
	engineers, total, err := h.Engineer.ListEngineers(c, param)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &engineerapi.ListEngineersResponse{Engineers: engineers, Total: total})
}

// GetEngineer gets one engineer by email.
//
//	@Summary	Get engineer
//	@Id			EngineerHandlerGetEngineer
//	@Tags		EngineerHandler
//	@Accept		json
//	@Produce	json
//	@Param		email	path		string	true	"Engineer email"
//	@Success	200		{object}	engineerapi.GetEngineerResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/engineers/{email} [get]
func (h *Handler) GetEngineer(c *gin.Context) {
	engineer, err := h.Engineer.GetEngineer(c, c.Param("email"))
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &engineerapi.GetEngineerResponse{Engineer: engineer})
}

// SyncEngineers runs the Core user reconciliation.
//
//	@Summary	Sync engineers
//	@Id			EngineerHandlerSyncEngineers
//	@Tags		EngineerHandler
//	@Accept		json
//	@Produce	json
//	@Success	200		{object}	engineerapi.SyncEngineersResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/engineers/sync [post]
func (h *Handler) SyncEngineers(c *gin.Context) {
	result, err := h.Engineer.SyncEngineers(c)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &engineerapi.SyncEngineersResponse{
		UsersScanned:     result.UsersScanned,
		EngineersCreated: result.EngineersCreated,
		EngineersUpdated: result.EngineersUpdated,
		EngineersDeleted: result.EngineersDeleted,
	})
}
