package central

import (
	"fmt"
	"message-service/commons/ginparser"
	"message-service/internal/bean/dto"
	service "message-service/internal/service/central"
	"net/http"
	"strings"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"

	"github.com/gin-gonic/gin"
)

// Chat with Bot godoc
// @Summary chat with bot
// @Description chat with bot
// @Tags message
// @Param org_id   path string true "org ID"
// @Param project_id path string true "project ID"
// @Param request_body body dto.InteractRequest true "request_body"
// @Accept json
// @Produce json
// @Success 200 {object} dto.InteractResponse
// @Router /orgs/{org_id}/projects/{project_id}/bot [post]
func InteractBot(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, fmt.Sprintf("ERROR: InteractBot param validate failed! err:%v, user:%s", validateErr, createdBy))
		c.Error(validateErr)
		return
	}
	req := &dto.InteractRequest{}
	err := params.BindParam(req)
	if err != nil {
		tilog.Error(ctx, fmt.Sprintf("ERROR: CreateApiKey param bind failed! err:%v, user:%s", err, createdBy))
		c.Error(err)
		return
	}
	// Set projectid
	req.ProjectID = params.ProjectID
	tilog.Info(ctx, "interact bot request", zap.Any("req", req))

	if invalidErr := service.CheckInteractReqeustValid(req); invalidErr != nil {
		tilog.Error(ctx, "CheckInteractReqeustValid failed", zap.Any("req", req), zap.Any("err", invalidErr))
		c.Error(invalidErr)
		return
	}
	rsp, err := service.InteractBot(ctx, req, createdBy)

	tilog.Info(ctx, "interact bot result", zap.Any("result", rsp), zap.Any("err", err))

	if err != nil {
		tilog.Error(ctx, "interact bot error", zap.Any("req", req), zap.Any("err", err))
		c.Error(err)
		return
	}

	c.JSON(http.StatusOK, rsp)
}

func Fail(c *gin.Context, code int, msg string) {
	c.JSON(code, gin.H{"code": code, "message": msg})
}

var validSortByCols = map[string]struct{}{
	"id":         {},
	"session_id": {},
	"question":   {},
	"response":   {},
	"created_by": {},
	"created_at": {},
	"updated_at": {},
}

var validOrderVals = map[string]struct{}{
	"asc":  {},
	"desc": {},
}

func ListInteractBotRecord(c *gin.Context) {
	req := &dto.ListInteractRecParam{}
	if err := c.ShouldBindQuery(req); err != nil {
		Fail(c, http.StatusBadRequest, "bad request")
		return
	}
	if req.SortBy != "" {
		lowerSortBy := strings.ToLower(req.SortBy)
		if _, ok := validSortByCols[lowerSortBy]; !ok {
			Fail(c, http.StatusBadRequest, "sort_by invalid")
			return
		}
		req.SortBy = lowerSortBy
	}
	if req.Order != "" {
		lowerOrder := strings.ToLower(req.Order)
		if _, ok := validOrderVals[lowerOrder]; !ok {
			Fail(c, http.StatusBadRequest, "order invalid")
			return
		}
		req.Order = lowerOrder
	}
	result, err := service.ListInteractBotRecord(c.Request.Context(), req)
	if err != nil {
		tilog.Error(c.Request.Context(), "list interact bot record error", zap.Any("req", req), zap.Any("err", err))
		Fail(c, http.StatusInternalServerError, "internal error")
		return
	}

	c.JSON(http.StatusOK, result)
}
