package agent

import (
	"github.com/gin-gonic/gin"
	"k8s.io/client-go/tools/clientcmd"

	"github.com/tidbcloud/devops/api"
	jmpapi "github.com/tidbcloud/devops/api/jump"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	"github.com/tidbcloud/devops/pkg/service/jump/jumppod/agent"
)

type JumpPodAgentController struct {
	agent *agent.JumpPodAgent
}

func NewJumpPodAgentController(agent *agent.JumpPodAgent) *JumpPodAgentController {
	return &JumpPodAgentController{agent: agent}
}

func (a *JumpPodAgentController) RegisterAPI(r gin.IRouter) {
	kg := r.Group("/kubernetes")
	{
		kg.POST("/rebuild", a.RebuildKubernetesCred)
		kg.GET("/credential", a.GetKubernetesCredential)
	}

	tg := r.Group("/tailscale")
	{
		tg.POST("/up", a.TailscaleUp)
		tg.POST("/down", a.TailscaleDown)
		tg.GET("/status", a.TailscaleStatus)
	}
}

func (a *JumpPodAgentController) RebuildKubernetesCred(ctx *gin.Context) {
	err := a.agent.KubernetesCred().Rebuild()
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, nil)
}

func (a *JumpPodAgentController) GetKubernetesCredential(ctx *gin.Context) {
	req := &jmpapi.GetKubernetesCredentialRequest{}
	if err := ctx.ShouldBindQuery(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}

	kubeconfig, err := a.agent.KubernetesCred().GetCredential(req.CredIDs)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	data, err := clientcmd.Write(*kubeconfig)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &jmpapi.GetKubernetesCredentialResponse{
		Kubeconfig: data,
	}
	ctrl.Success(ctx, resp)
}

func (a *JumpPodAgentController) TailscaleUp(ctx *gin.Context) {
	req := &jmpapi.TailscaleUpRequest{}
	err := ctx.ShouldBindJSON(req)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}

	opt := agent.TailscaleUpOptions{
		Hostname: req.Hostname,
		AuthKey:  req.AuthKey,
	}
	err = a.agent.Tailscale().TailscaleUp(ctx, opt)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, nil)
}

func (a *JumpPodAgentController) TailscaleDown(ctx *gin.Context) {
	err := a.agent.Tailscale().TailscaleDown(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, nil)
}

func (a *JumpPodAgentController) TailscaleStatus(ctx *gin.Context) {
	status, err := a.agent.Tailscale().TailscaleStatus(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &jmpapi.TailscaleStatusResponse{
		Status: status,
	}
	ctrl.Success(ctx, resp)
}
