package dedicatedregional

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"sigs.k8s.io/controller-runtime/pkg/client"

	v1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	bizerr "github.com/tidbcloud/infra-provider/regional-server/pkg/common/errors"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/router/interceptor"
	migrationrs "github.com/tidbcloud/infra-provider/regional-server/pkg/service/migration/dedicatedregional"
)

type Handler struct {
	svc *migrationrs.Service
}

func NewHandler(svc *migrationrs.Service) *Handler {
	return &Handler{
		svc: svc,
	}
}

func (handler *Handler) ImportAPPBox(c *gin.Context) {
	cr := new(v1alpha1.APPBox)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportAPPBox(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckAPPBox(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckAPPBox(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileAPPBox(c *gin.Context) {
	cr := new(v1alpha1.APPBox)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	if !pause {
		if err := handler.svc.SetAnnoSkipGC(c, cr, false); err != nil {
			interceptor.Fail(c, err)
			return
		}
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportAPPRoute(c *gin.Context) {
	cr := new(v1alpha1.APPRoute)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportAPPRoute(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckAPPRoute(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckAPPRoute(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileAPPRoute(c *gin.Context) {
	cr := new(v1alpha1.APPRoute)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportInternet(c *gin.Context) {
	cr := new(v1alpha1.Internet)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportInternet(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckInternet(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckInternet(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileInternet(c *gin.Context) {
	cr := new(v1alpha1.Internet)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	if !pause {
		if err := handler.svc.SetAnnoSkipGC(c, cr, false); err != nil {
			interceptor.Fail(c, err)
			return
		}
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportPrivateLinkService(c *gin.Context) {
	cr := new(v1alpha1.PrivateLinkService)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportPrivateLinkService(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckPrivateLinkService(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckPrivateLinkService(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcilePrivateLinkService(c *gin.Context) {
	cr := new(v1alpha1.PrivateLinkService)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportVPCPeering(c *gin.Context) {
	cr := new(v1alpha1.VPCPeering)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportVPCPeering(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckVPCPeering(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckVPCPeering(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileVPCPeering(c *gin.Context) {
	cr := new(v1alpha1.VPCPeering)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportVPC(c *gin.Context) {
	cr := new(v1alpha1.VPC)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportVPC(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckVPC(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckVPC(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileVPC(c *gin.Context) {
	cr := new(v1alpha1.VPC)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ImportO11yRoute(c *gin.Context) {
	cr := new(v1alpha1.O11yRoute)
	if err := c.BindJSON(cr); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.ImportO11yRoute(c, cr); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) CheckO11yRoute(c *gin.Context) {
	key := client.ObjectKey{
		Name: c.Query("name"),
	}
	if err := handler.svc.CheckO11yRoute(c, key); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) ReconcileO11yRoute(c *gin.Context) {
	cr := new(v1alpha1.O11yRoute)
	cr.Name = c.Query("name")
	pause, err := strconv.ParseBool(c.Query("pause"))
	if err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	if err := handler.svc.PauseReconcile(c, cr, pause); err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusAccepted, struct{}{})
}

func (handler *Handler) DiffEKSClusterSpec(c *gin.Context) {
	clusterID := c.Query("clusterID")
	if clusterID == "" {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, "clusterID is empty"))
		return
	}
	spec := new(v1.EKSClusterSpec)
	if err := c.BindJSON(spec); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	err := handler.svc.CheckEKSClusterSpec(c, clusterID, spec)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusOK, struct{}{})
}

func (handler *Handler) DiffGKEClusterSpec(c *gin.Context) {
	clusterID := c.Query("clusterID")
	if clusterID == "" {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, "clusterID is empty"))
		return
	}
	spec := new(v1.GKEClusterSpec)
	if err := c.BindJSON(spec); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParamParseError, err.Error()))
		return
	}
	err := handler.svc.CheckGKEClusterSpec(c, clusterID, spec)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.Succeed(c, http.StatusOK, struct{}{})
}
