package framework

import (
	"context"
	"fmt"
	"time"

	httptransport "github.com/go-openapi/runtime/client"
	"github.com/go-openapi/strfmt"
	"github.com/onsi/gomega"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"

	"github.com/pingcap/test-infra/common/model/resource"
	"github.com/pingcap/test-infra/sdk/dbaas_central/client"
	"github.com/pingcap/test-infra/sdk/dbaas_central/client/cluster_service"
	"github.com/pingcap/test-infra/sdk/pkg/tidbcloud"
	"github.com/pingcap/test-infra/sdk/resource/impl/k8s"
)

func (f *Framework) CreateTiDBCloudCluster(testbed *k8s.Testbed, config tidbcloud.TiDBCloudConfiguration) *k8s.TiDBCloudCluster {
	client, err := k8s.NewTiDBCloudClusterClient(f.KubeClientSetPack, &config)
	ExpectNoError(err)

	r, err := client.Create([]byte(fmt.Sprintf(`{
  "name": "tc",
  "type": "TIDBCLOUD_CLUSTER",
  "testbed": "%s",
  "spec": {
    "accountEmail": "manjunpeng@pingcap.com",
    "orgID": "1369847559691367419",
    "projectID": "1369847559691427556",
    "provider": "aws",
    "connect": "standard",
    "password": "5631qmpWX#t6uDV6",
    "tidb": {
      "replicas": 1,
      "nodeProfileName": "4 vCPU, 16 GiB (Beta)"
    },
    "tikv": {
      "replicas": 3,
      "nodeProfileName": "4 vCPU, 16 GiB (Beta)",
      "storageSizeGi": 200
    },
    "clusterConfig": {
      "tikv": {
        "config": "log-level = \"debug\""
      }
    }
  }
}`, testbed.Name)))
	ExpectNoError(err)
	return r.(*k8s.TiDBCloudCluster)
}
func (f *Framework) WaitForTiDBCloudClusterReadyWithoutPing(c *k8s.TiDBCloudCluster, timeout time.Duration) {
	k8s.SetConfig(k8s.Config{
		TiDBCloudClusterConfig: k8s.TiDBCloudClusterConfig{
			ReadyCheck: k8s.TiDBCloudClusterReadyCheckConfig{
				PingDB: false,
			},
		},
	})
	ExpectNoError(c.WaitForReady(timeout))
}

func (f *Framework) WaitForTiDBCloudClusterReady(c *k8s.TiDBCloudCluster, timeout time.Duration) {
	ExpectNoError(c.WaitForReady(timeout))
}

func (f *Framework) DeleteTiDBCloudCluster(config tidbcloud.TiDBCloudConfiguration, handle resource.ResourceHandle) {
	client, err := k8s.NewTiDBCloudClusterClient(f.KubeClientSetPack, &config)
	ExpectNoError(err)
	ExpectNoError(client.Delete(handle))
}

func (f *Framework) CreateTiDBCloudClusterController(config tidbcloud.TiDBCloudConfiguration) *k8s.TiDBCloudObjectController {
	clientSet, err := k8s.NewTiDBCloudKubeClientSet(&config)
	ExpectNoError(err)
	ctl, err := k8s.NewTiDBCloudClusterController(f.KubeClientSetPack.ClientSet, clientSet, config)
	ExpectNoError(err)
	return ctl
}

func (f *Framework) DeleteTiDBCloudClusterObj(client kubernetes.Interface, ns string, name string) *corev1.Secret {
	secret, err := client.CoreV1().Secrets(ns).Get(context.TODO(), fmt.Sprintf("tidbcloud-%s", name), metav1.GetOptions{})
	ExpectNoError(err)
	err = client.CoreV1().Secrets(ns).Delete(context.TODO(), fmt.Sprintf("tidbcloud-%s", name), metav1.DeleteOptions{})
	ExpectNoError(err)
	return secret
}
func (f *Framework) WaitTiDBCloudClusterDeleted(config tidbcloud.TiDBCloudConfiguration, ns string, name string, clusterId string, token string, orgID string, projectID string) {
	tidbCloudClient := client.NewHTTPClientWithConfig(strfmt.Default, client.DefaultTransportConfig().WithHost(config.TiDBCloudURL).WithSchemes([]string{"https"}))
	err := wait.PollImmediate(10*time.Second, 2*time.Minute, func() (done bool, err error) {
		_, err = f.KubeClientSetPack.ClientSet.CoreV1().Secrets(ns).Get(context.TODO(), fmt.Sprintf("tidbcloud-%s", name), metav1.GetOptions{})
		if errors.IsNotFound(err) {
			return true, nil
		}
		return false, err
	})
	ExpectNoError(err)
	resp, err := tidbCloudClient.ClusterService.GetCluster(&cluster_service.GetClusterParams{
		ID:        clusterId,
		OrgID:     orgID,
		ProjectID: projectID,
		Context:   context.TODO(),
	}, httptransport.BearerToken(token))

	gomega.Expect(resp.GetPayload().Cluster).Should(gomega.BeNil())
	ExpectNoError(err)
}
