package api

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"

	"github.com/tidbcloud/alertstore/pkg/subscription"
)

// @Summary	List the mute rules that have not expired
// @Id			listMuteRules
// @Tags		MuteRules
// @Produce	json
// @Success	200	{array}		mute.Rule
// @Failure	500	{object}	ErrorResponse
// @Router		/mute-rules [get]
func (s *Server) listMuteRules(c *gin.Context) {
	rules, err := s.muteStore.ListActive(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, errorBody(err))
		return
	}
	c.JSON(http.StatusOK, rules)
}

type createMuteRuleRequest struct {
	Filter    json.RawMessage `json:"filter" binding:"required" swaggertype:"object"`
	Reason    string          `json:"reason"`
	CreatedBy string          `json:"created_by"`
	Duration  string          `json:"duration" binding:"required"` // e.g. "2h", "30m"
}

// @Summary	Create a mute rule
// @Id			createMuteRule
// @Tags		MuteRules
// @Accept		json
// @Produce	json
// @Param		body	body		createMuteRuleRequest	true	"Filter and lifetime"
// @Success	201		{object}	mute.Rule
// @Failure	400		{object}	ErrorResponse	"Invalid filter or duration"
// @Failure	500		{object}	ErrorResponse
// @Router		/mute-rules [post]
func (s *Server) createMuteRule(c *gin.Context) {
	var req createMuteRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, errorBody(err))
		return
	}

	if err := subscription.ValidateMuteFilter(req.Filter); err != nil {
		c.JSON(http.StatusBadRequest, errorBody(err))
		return
	}

	d, err := time.ParseDuration(req.Duration)
	if err != nil {
		c.JSON(http.StatusBadRequest, errorMessage("invalid duration: "+err.Error()))
		return
	}

	expiresAt := time.Now().Add(d)
	rule, err := s.muteStore.Create(c.Request.Context(), req.Filter, req.Reason, req.CreatedBy, expiresAt)
	if err != nil {
		c.JSON(http.StatusInternalServerError, errorBody(err))
		return
	}
	c.JSON(http.StatusCreated, rule)
}

type updateMuteRuleRequest struct {
	Filter    json.RawMessage `json:"filter" binding:"required" swaggertype:"object"`
	Reason    string          `json:"reason"`
	ExpiresAt *time.Time      `json:"expires_at"`
	Duration  string          `json:"duration"`
}

// @Summary	Update a mute rule
// @Id			updateMuteRule
// @Tags		MuteRules
// @Accept		json
// @Produce	json
// @Param		id		path		string					true	"Mute rule id"
// @Param		body	body		updateMuteRuleRequest	true	"Updated filter, reason, and expiry"
// @Success	200		{object}	mute.Rule
// @Failure	400		{object}	ErrorResponse	"Invalid filter, duration, or expires_at"
// @Failure	404		{object}	ErrorResponse
// @Failure	500		{object}	ErrorResponse
// @Router		/mute-rules/{id} [put]
func (s *Server) updateMuteRule(c *gin.Context) {
	var req updateMuteRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, errorBody(err))
		return
	}

	if err := subscription.ValidateMuteFilter(req.Filter); err != nil {
		c.JSON(http.StatusBadRequest, errorBody(err))
		return
	}

	existing, err := s.muteStore.Get(c.Request.Context(), c.Param("id"))
	if err != nil {
		c.JSON(http.StatusNotFound, errorMessage("mute rule not found"))
		return
	}

	expiresAt := existing.ExpiresAt
	switch {
	case req.ExpiresAt != nil:
		expiresAt = *req.ExpiresAt
	case req.Duration != "":
		d, err := time.ParseDuration(req.Duration)
		if err != nil {
			c.JSON(http.StatusBadRequest, errorMessage("invalid duration: "+err.Error()))
			return
		}
		expiresAt = time.Now().Add(d)
	}

	if err := s.muteStore.Update(c.Request.Context(), c.Param("id"), req.Filter, req.Reason, expiresAt); err != nil {
		c.JSON(http.StatusInternalServerError, errorBody(err))
		return
	}
	existing.Filter = req.Filter
	existing.Reason = req.Reason
	existing.ExpiresAt = expiresAt
	c.JSON(http.StatusOK, existing)
}

// @Summary	Delete a mute rule
// @Id			deleteMuteRule
// @Tags		MuteRules
// @Produce	json
// @Param		id	path		string	true	"Mute rule id"
// @Success	200	{object}	StatusResponse
// @Failure	500	{object}	ErrorResponse
// @Router		/mute-rules/{id} [delete]
func (s *Server) deleteMuteRule(c *gin.Context) {
	if err := s.muteStore.Delete(c.Request.Context(), c.Param("id")); err != nil {
		c.JSON(http.StatusInternalServerError, errorBody(err))
		return
	}
	c.JSON(http.StatusOK, okStatus())
}
