package cluster

import (
	"context"
	"fmt"

	"github.com/gin-gonic/gin"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	cloudv1 "pingcap.com/cloud/v2/cluster/api/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type ClusterReq struct {
	ClusterName     string `json:"cluster_name" binding:"required"`
	ClusterSpecName string `json:"cluster_spec_name"`
}

type ClusterService struct {
	centralClient client.Client
}

func RegisterRouter(router *gin.Engine, c *ClusterService) {
	cluster := router.Group("/api/clusters")

	v1 := cluster.Group("/v1")
	{
		// ClusterService:
		v1.GET("", c.ListCluster)
		v1.POST("", c.CreateCluster)
		v1.GET(":cluster_id", c.GetCluster)
		v1.DELETE(":cluster_id", c.DeleteCluster)
	}

	// v2 := cluster.Group("/v2")
	// {
	// 	v2.GET("", c.ListCluster)
	// 	v2.PUT("/create", c.CreateCluster)
	// 	v2.GET(":id", c.GetCluster)
	// 	v2.PATCH("/update", c.UpdateCluster)
	// 	v2.DELETE("/delete", c.DeleteCluster)
	// }
}

func NewClusterService(client client.Client) *ClusterService {
	return &ClusterService{
		centralClient: client,
	}
}

func (c *ClusterService) ListCluster(ctx *gin.Context) {
	list := &cloudv1.ClusterList{}
	err := c.centralClient.List(context.TODO(), list, &client.ListOptions{})
	if err != nil {
		ctx.JSON(500, gin.H{
			"status": "error",
		})
	}
	clusterList := []string{}
	for _, cluster := range list.Items {
		clusterList = append(clusterList, cluster.Name)
	}
	ctx.JSON(200, gin.H{
		"clusterList": clusterList,
	})
}

func (c *ClusterService) GetCluster(ctx *gin.Context) {
	ctx.JSON(200, gin.H{
		"status": ctx.Param("id"),
	})
}

func (c *ClusterService) CreateCluster(ctx *gin.Context) {
	var req ClusterReq
	ctx.BindJSON(&req)
	cluster := &cloudv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      req.ClusterName,
			Namespace: "default",
		},
		Spec: cloudv1.ClusterSpec{
			Name: req.ClusterName,
		},
	}

	if err := c.centralClient.Create(context.TODO(), cluster); err != nil {
		ctx.JSON(500, gin.H{
			"status": "error",
		})
	} else {
		ctx.JSON(200, gin.H{
			"status": "ok",
		})
	}
}

func (c *ClusterService) UpdateCluster(ctx *gin.Context) {
	var req ClusterReq
	ctx.BindJSON(&req)
	var cluster cloudv1.Cluster
	c.centralClient.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: req.ClusterName}, &cluster)
	cluster.Spec.Name = req.ClusterSpecName
	if err := c.centralClient.Update(context.TODO(), &cluster); err != nil {
		fmt.Println(err)
		ctx.JSON(500, gin.H{
			"status": "error",
		})
	} else {
		ctx.JSON(200, gin.H{
			"status": "ok",
		})
	}
}

func (c *ClusterService) DeleteCluster(ctx *gin.Context) {
	var req ClusterReq
	ctx.BindJSON(&req)
	cluster := &cloudv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      req.ClusterName,
			Namespace: "default",
		},
	}
	if err := c.centralClient.Delete(context.TODO(), cluster); err != nil {
		ctx.JSON(500, gin.H{
			"status": "error",
		})
	} else {
		ctx.JSON(200, gin.H{
			"status": "ok",
		})
	}
}
