package tidbcluster

import (
	"context"
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	apiresource "github.com/pingcap/test-infra/common/model/resource"
	"github.com/pingcap/test-infra/sdk/resource"

	"github.com/pingcap/test-infra/sdk/e2etest/framework"
)

var _ = Describe("Lightning Test", func() {
	Context("Lightning.Create", func() {
		f := framework.NewDefaultFramework("testbed-lightning-create")

		It("Lightning's testbed should equal to testbed's name", func() {
			lightning := f.CreateLightning(f.CreateTestbed())
			Expect(lightning.Testbed).Should(Equal(f.Testbed()))
			Expect(lightning.Type).Should(Equal(apiresource.ResourceTypeTiDBLightning))
		})

		It("Lightning should be ready after a while", func() {
			lightning := f.CreateLightning(f.CreateTestbed())

			err := f.WaitForLightningReady(lightning, framework.TestContext.ResourceWaitReadyTimeout)
			framework.ExpectNoError(err)
		})
	})

	Context("Lightning.Get", func() {
		f := framework.NewDefaultFramework("testbed-lightning-get")

		It("Lightning's testbed should equal to testbed's name", func() {
			lightning := f.CreateLightning(f.CreateTestbed())
			lightning = f.GetLightning(lightning.Handle())

			Expect(lightning.Testbed).Should(Equal(f.Testbed()))
			Expect(lightning.Type).Should(Equal(apiresource.ResourceTypeTiDBLightning))
		})

		It("Lightning should be ready after a while", func() {
			lightning := f.CreateLightning(f.CreateTestbed())
			lightning = f.GetLightning(lightning.Handle())

			err := f.WaitForLightningReady(lightning, framework.TestContext.ResourceWaitReadyTimeout)
			framework.ExpectNoError(err)
		})
	})

	Context("Lightning.Archive", func() {
		f := framework.NewDefaultFramework("testbed-lightning-archive")

		It("Lightning.Archive should work well", func() {
			lightning := f.CreateLightning(f.CreateTestbed())
			lightning = f.GetLightning(lightning.Handle())

			err := f.WaitForLightningReady(lightning, framework.TestContext.ResourceWaitReadyTimeout)
			framework.ExpectNoError(err)

			_, _, _, err = lightning.Exec(resource.WorkloadNodeExecOptions{Command: "echo test-infra > /tmp/lightning.log.1"})
			framework.ExpectNoError(err)
			var data []string

			f.ArchiveLightning(lightning.Handle(), f.Archiver(&data))
			Expect(len(data)).Should(Equal(1))
			Expect(data[0]).Should(ContainSubstring("test-infra"))
		})
	})

	Context("Lightning.Delete", func() {
		f := framework.NewDefaultFramework("testbed-lightning-delete")

		It("Lightning's delete should clean all resources", func() {
			lightning := f.CreateLightning(f.CreateTestbed())

			f.DeleteLightningWaited(lightning)

			pods := f.AllPods()
			Expect(len(pods.Items)).Should(Equal(0))
			Expect(len(f.AllPVCs().Items)).Should(Equal(0))
			Expect(len(f.AllServices().Items)).Should(Equal(0))
			Expect(len(f.AllConfigmaps().Items)).Should(Equal(1))
		})
	})

	Context("Lightning.Exec", func() {
		f := framework.NewDefaultFramework("testbed-lightning-exec")

		It("Lightning's lightning -V", func() {
			lightning := f.CreateLightning(f.CreateTestbed())
			f.WaitForLightningReady(lightning, framework.TestContext.ResourceWaitReadyTimeout)

			stdout, _, _, _ := lightning.Exec(resource.WorkloadNodeExecOptions{Command: "/tidb-lightning -V"})
			Expect(stdout).Should(Equal(`Release Version: v5.0.1
Git Commit Hash: b3bd5495369244cfb1d3f2c49763a7fdb55d4ecd
Git Branch: heads/refs/tags/v5.0.1
Go Version: go1.13
UTC Build Time: 2021-04-23 06:02:57
Race Enabled: false`))
		})
	})
	Context("LightningWithQos.Create", func() {
		f := framework.NewDefaultFramework("testbed-lightning-with-qos-create")
		It("Lightning qos should work", func() {
			lightling := f.CreateLightningWithQos(f.CreateTestbedWithQos())
			err := f.WaitForLightningReady(lightling, time.Hour)
			framework.ExpectNoError(err)

			expectedPodName := fmt.Sprintf("%s-0", lightling.Name)
			pod, err := f.KubeClientSetPack.ClientSet.
				CoreV1().
				Pods(lightling.Namespace).
				Get(context.TODO(), expectedPodName, metav1.GetOptions{})
			framework.ExpectNoError(err)
			item, ok := pod.Labels["naglfar/podgroup"]
			framework.ExpectEqual(ok, true)
			framework.ExpectEqual(item, fmt.Sprintf("%s.%s", "cluster-1", lightling.Name))
		})
	})
})
