package dispatch

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	dispatchapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/ticket-manager/dispatch"
	dispatchent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/dispatch"
	apiutils "github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver/utils"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/errs"
	dispatchsvcapi "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/dispatch/api"
)

// CreateDispatchTrigger creates an outbox trigger for dispatch.
//
//	@Summary	Create dispatch trigger
//	@Id			DispatchHandlerCreateDispatchTrigger
//	@Tags		DispatchHandler
//	@Accept		json
//	@Produce	json
//	@Param		request	body		dispatchapi.CreateDispatchTriggerRequest	true	"Trigger payload"
//	@Success	200		{object}	dispatchapi.CreateDispatchTriggerResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/dispatch/triggers [post]
func (h *Handler) CreateDispatchTrigger(c *gin.Context) {
	var req dispatchapi.CreateDispatchTriggerRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	trigger, err := h.Dispatch.Dispatch(c, dispatchsvcapi.DispatchParam{
		Source: req.Source, Input: dispatchent.DispatchTriggerInput{IssueKey: req.Input.IssueKey},
		PolicyID: req.PolicyID, Dryrun: req.Dryrun,
	})
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &dispatchapi.CreateDispatchTriggerResponse{Trigger: trigger})
}

// GetDispatchTrigger returns one dispatch trigger.
//
//	@Summary	Get dispatch trigger
//	@Id			DispatchHandlerGetDispatchTrigger
//	@Tags		DispatchHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Trigger ID"
//	@Success	200		{object}	dispatchapi.GetDispatchTriggerResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/dispatch/triggers/{id} [get]
func (h *Handler) GetDispatchTrigger(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	trigger, err := h.Dispatch.GetDispatchTrigger(c, id)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &dispatchapi.GetDispatchTriggerResponse{Trigger: trigger})
}

// ListDispatchTriggers lists dispatch triggers.
//
//	@Summary	List dispatch triggers
//	@Id			DispatchHandlerListDispatchTriggers
//	@Tags		DispatchHandler
//	@Accept		json
//	@Produce	json
//	@Param		param	query		dispatchapi.ListDispatchTriggersRequest	false	"param"
//	@Success	200		{object}	dispatchapi.ListDispatchTriggersResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/dispatch/triggers [get]
func (h *Handler) ListDispatchTriggers(c *gin.Context) {
	var req dispatchapi.ListDispatchTriggersRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	param := dispatchsvcapi.ListDispatchTriggersParam{
		Statuses: req.Statuses,
		Page:     dispatchsvcapi.PageParam{Page: int(req.Page), PageSize: int(req.PageSize)},
	}
	if req.IssueKeyLike != "" {
		param.IssueKeyLike = &req.IssueKeyLike
	}
	if req.Source != "" {
		param.Source = &req.Source
	}
	triggers, total, err := h.Dispatch.ListDispatchTriggers(c, param)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &dispatchapi.ListDispatchTriggersResponse{Triggers: triggers, Total: total})
}

// GetExecution returns one dispatch execution with its evaluations.
//
//	@Summary	Get dispatch execution
//	@Id			DispatchHandlerGetExecution
//	@Tags		DispatchHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Execution ID"
//	@Success	200		{object}	dispatchapi.GetExecutionResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/dispatch/executions/{id} [get]
func (h *Handler) GetExecution(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	execution, err := h.Dispatch.GetExecution(c, id)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &dispatchapi.GetExecutionResponse{Execution: execution})
}

// ListExecutions lists dispatch executions.
//
//	@Summary	List dispatch executions
//	@Id			DispatchHandlerListExecutions
//	@Tags		DispatchHandler
//	@Accept		json
//	@Produce	json
//	@Param		param	query		dispatchapi.ListExecutionsRequest	false	"param"
//	@Success	200		{object}	dispatchapi.ListExecutionsResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/dispatch/executions [get]
func (h *Handler) ListExecutions(c *gin.Context) {
	var req dispatchapi.ListExecutionsRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}
	param := dispatchsvcapi.ListExecutionsParam{
		Statuses: req.Statuses,
		Page:     dispatchsvcapi.PageParam{Page: int(req.Page), PageSize: int(req.PageSize)},
	}
	if req.IssueKeyLike != "" {
		param.IssueKeyLike = &req.IssueKeyLike
	}
	if req.PolicyFamilyID != "" {
		param.PolicyFamilyIDIs = &req.PolicyFamilyID
	}
	if req.Mode != "" {
		param.Mode = &req.Mode
	}
	executions, total, err := h.Dispatch.ListExecutions(c, param)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}
	apiutils.Success(c, &dispatchapi.ListExecutionsResponse{Executions: executions, Total: total})
}
