package cluster

import (
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/pingcap-inc/clinic/pkg/api/common"
	error2 "github.com/pingcap-inc/clinic/pkg/api/error"
	"github.com/pingcap-inc/clinic/pkg/datasource/model"
	"github.com/pingcap-inc/clinic/pkg/db"
	"github.com/pingcap-inc/clinic/pkg/stream"
)

// @Summary		get cluster slogan
// @Tags			Cluster Slogan
// @Description	get cluster slogan
// @Accept			json
// @Param			x-csrf-token	header		string	true	"get value from login.ValidationResp response"
// @Param			oid				path		string	true	"organization id"
// @Param			cid				path		string	true	"cluster id"
// @Param			limit			query		int		false	"the count per page"
// @Param			page			query		int		false	"the page index"
// @Success		200				{object}	SloganRespList
// @Router			/orgs/{oid}/clusters/{cid}/slogans [get]
func (s *ClusterService) ListSlogans(c *gin.Context) {
	_, org, cluster, ok, err := common.CanReadCluster(c, s.rbac, c.Param("cid"))
	if err != nil {
		_ = c.Error(error2.ErrNotFound.New("%s", err.Error()))
		return
	}

	if !ok {
		_ = c.Error(error2.ErrForbidden.New("access cluster failed"))
		return
	}

	pq := common.ParsePaginationQuery(c.Request.URL.RequestURI())

	slogans, totol, err := model.ListSlogans(org.ID, cluster.ClusterID, pq.Page, pq.Limit)
	if err != nil {
		_ = c.Error(error2.ErrInternal.New("query slogan failed"))
		log.Error("query slogan failed", zap.Error(err))
		return
	}

	results := make([]SloganResp, 0)
	stream.OfSlice(slogans).Map(func(s db.Slogan) SloganResp {
		return SloganResp{
			ID:       s.ID,
			CreateAt: s.CreatedAt.Unix(),
			Text:     s.Text,
		}
	}).CollectEmptySlice(&results)

	c.JSON(http.StatusOK, SloganRespList{
		Total: totol,
		Items: results,
	})
}

func (s *ClusterService) AddSlogan(c *gin.Context) {
	u, org, cluster, ok, err := common.CanReadCluster(c, s.rbac, c.Param("cid"))
	if err != nil {
		_ = c.Error(error2.ErrNotFound.New("%s", err.Error()))
		return
	}
	if !ok {
		_ = c.Error(error2.ErrForbidden.New("access cluster failed"))
		return
	}
	if !u.Internal {
		_ = c.Error(error2.ErrForbidden.New("permission deny"))
		return
	}

	var val SloganReq
	if err := c.BindJSON(&val); err != nil {
		_ = c.Error(error2.ErrBadRequest.New("bad parameter"))
		return
	}

	result, err := model.CreateSlogan(org.ID, cluster.ClusterID, val.Text)
	if err != nil {
		log.Error("create slogan failed", zap.Error(err))
		_ = c.Error(error2.ErrInternal.New("create slogan failed"))
		return
	}

	c.JSON(http.StatusOK, SloganResp{
		ID:       result.ID,
		Text:     result.Text,
		CreateAt: time.Now().Unix(),
	})
}

func (s *ClusterService) DeleteSlogans(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		_ = c.Error(error2.ErrBadRequest.New("invalid id"))
		return
	}

	u, _, _, ok, err := common.CanReadCluster(c, s.rbac, c.Param("cid"))
	if err != nil {
		_ = c.Error(error2.ErrNotFound.New("%s", err.Error()))
		return
	}
	if !ok {
		_ = c.Error(error2.ErrForbidden.New("access cluster failed"))
		return
	}
	if !u.Internal {
		_ = c.Error(error2.ErrForbidden.New("permission deny"))
		return
	}

	if err = model.DeleteSlogan(int(id)); err != nil {
		log.Error("delete slogan failed", zap.Error(err))
		_ = c.Error(error2.ErrInternal.New("delete slogan failed"))
		return
	}
	c.JSON(http.StatusOK, common.SuccessResponse())
}
