package ops

import (
	"context"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"

	apierr "github.com/pingcap-inc/clinic/pkg/api/error"
	"github.com/pingcap-inc/clinic/pkg/rbac"
	"github.com/pingcap-inc/clinic/pkg/resource_limit"
)

type BackdoorAPI struct {
	rbacAuth rbac.Auth
}

func NewBackdoorAPI(rbacAuth rbac.Auth) (*BackdoorAPI, error) {
	return &BackdoorAPI{rbacAuth: rbacAuth}, nil
}

func (api *BackdoorAPI) InsertCasbinRule(ctx context.Context, param *CasbinRuleParam) (bool, error) {
	values := strings.Split(param.Rule, ",")
	if len(values) <= 1 {
		return false, fmt.Errorf("rule [%s] is not valid", param.Rule)
	}
	pType := values[0]
	values = values[1:]
	if pType == "p" {
		return api.rbacAuth.GetEnforcer().AddPolicy(values)
	}
	if pType == "g" {
		return api.rbacAuth.GetEnforcer().AddGroupingPolicy(values)
	}
	return false, fmt.Errorf("p_type [%s] is not valid", pType)
}

func (api *BackdoorAPI) InsertCasbinRuleGinHandler(c *gin.Context) {
	param := &CasbinRuleParam{}
	if err := c.BindJSON(param); err != nil {
		_ = c.Error(apierr.ErrBadRequest.WrapWithNoMessage(err))
		return
	}
	ok, err := api.InsertCasbinRule(c.Request.Context(), param)
	if err != nil {
		_ = c.Error(apierr.ErrInternal.WrapWithNoMessage(err))
		return
	}
	resp := struct {
		Result bool `json:"result"`
	}{
		ok,
	}
	c.JSON(http.StatusOK, resp)
}

func (api *BackdoorAPI) SyncAllCloudClusters(c *gin.Context) {
	job := resource_limit.MigrateFullClusterJob{
		ForceUpdate: c.GetBool("forceUpdate"),
	}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncAllServerlessClusters(c *gin.Context) {
	job := resource_limit.MigrateFullServerlessClusterJob{
		ForceUpdate:    c.GetBool("forceUpdate"),
		IncludeDeleted: c.GetBool("deleted"),
	}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncAllMgmtClusters(c *gin.Context) {
	job := resource_limit.MigrateMgmtClusterJob{
		ForceUpdate: c.GetBool("forceUpdate"),
	}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncAllCloudOrgs(c *gin.Context) {
	job := resource_limit.MigrateOrganizationJob{UpdatePlan: true}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncDeployType(c *gin.Context) {
	job := resource_limit.SyncDeployTypeJob{}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) MigrateDeployType(c *gin.Context) {
	job := resource_limit.MigrateDeployTypeJob{}
	job.Run()
	c.String(http.StatusOK, "migrated")
}

func (api *BackdoorAPI) SyncParentIdJob(c *gin.Context) {
	job := resource_limit.SyncParentIdJob{}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncResourcePool(c *gin.Context) {
	job := resource_limit.SyncResourcePool{
		ForceUpdate: c.GetBool("forceUpdate"),
	}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) SyncResourcePoolStatus(c *gin.Context) {
	job := resource_limit.SyncResourcePoolStatus{}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}

func (api *BackdoorAPI) MigrateClusterStatus(c *gin.Context) {
	job := resource_limit.MigrateClusterStatusJob{}
	job.Run()
	c.String(http.StatusOK, "sync finished")
}
