// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.package spec

package e2e

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/pingcap/tidb-cloud-manager/test/e2e/framework"
	"github.com/pingcap/private-tidb-operator/pkg/client"
	opbootstrap "github.com/pingcap/private-tidb-operator/test/e2e/bootstrap"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"testing"
)

var bootstrap *framework.Bootstrap
var opbs *opbootstrap.Bootstrap
var writer *bufio.Writer

func init() {
	flag.StringVar(&opbootstrap.OperatorImage, "operator-image", "", "The tidb-operator image")
}

func TestE2e(t *testing.T) {
	RegisterFailHandler(failWrapper)
	logPath := fmt.Sprintf("/logdir/%d", config.GinkgoConfig.RandomSeed)
	if _, err := os.Stat(logPath); os.IsNotExist(err) {
		err = os.MkdirAll(logPath, os.ModePerm)
		if err != nil {
			panic(err)
		}
	}
	logFile, err := os.Create(filepath.Join(logPath, fmt.Sprintf("%d", config.GinkgoConfig.ParallelNode)))
	if err != nil {
		panic(err)
	}
	writer = bufio.NewWriter(logFile)

	RunSpecs(t, "TiDB Cloud Manager e2e tests")
}

var _ = BeforeSuite(func() {
	By("Bootstrapping Tidb Cloud Manager")

	var err error
	opbs, err = opbootstrap.New()
	Expect(err).NotTo(HaveOccurred())

	err = opbs.DeleteOperator()
	if err != nil {
		framework.Infof(err.Error())
	}
	Expect(opbs.WaitOperatorDeleted()).To(Succeed())

	bootstrap, err = framework.New()
	Expect(err).NotTo(HaveOccurred())
	Expect(bootstrap.Setup()).To(Succeed())

	Expect(opbs.ApplyOperator()).To(Succeed())
	Expect(opbs.SetupTidbVolumeConfigMap()).To(Succeed())
	Expect(opbs.ClearPVs()).To(Succeed())
})

var _ = AfterSuite(func() {
	By("Tear down test environment")

	Expect(bootstrap.TearDown()).To(Succeed())
	Expect(opbs.Teardown()).To(Succeed())
})

func failWrapper(message string, callerSkip ...int) {
	defer Fail(message, callerSkip...)

	ns := clusterName
	dumpLog("kubectl get po -owide -n kube-system")
	dumpLog("kubectl get po -owide -n pingcap")
	dumpLog(fmt.Sprintf("kubectl get po,pvc,svc,cm,tidbinstances,tidbclusters,tidbsets -owide -n %s", ns))
	dumpLog(fmt.Sprintf("kubectl get po,pvc,svc,cm,tidbinstances,tidbclusters,tidbsets -n %s -oyaml", ns))
	dumpLog("kubectl get pv")
	dumpLog("kubectl get pv -oyaml")

	cli, err := client.New("")
	if err != nil {
		framework.Errorf(err.Error())
		return
	}
	pingcapPodList, err := cli.CoreV1().Pods("pingcap").List(metav1.ListOptions{})
	if err != nil {
		framework.Errorf(err.Error())
		return
	}
	for _, pod := range pingcapPodList.Items {
		dumpLog(fmt.Sprintf("kubectl -n pingcap get po  %s -o yaml", pod.GetName()))
		for _, c := range pod.Spec.Containers {
			dumpLog(fmt.Sprintf("kubectl logs -n pingcap %s -c %s", pod.GetName(), c.Name))
			dumpLog(fmt.Sprintf("kubectl logs -n pingcap %s -c %s -p", pod.GetName(), c.Name))
		}
	}

	e2ePodList, err := cli.CoreV1().Pods(ns).List(metav1.ListOptions{})
	if err != nil {
		framework.Errorf(err.Error())
		return
	}
	for _, pod := range e2ePodList.Items {
		dumpLog(fmt.Sprintf("kubectl -n %s get po  %s -o yaml", ns, pod.GetName()))
		for _, c := range pod.Spec.Containers {
			dumpLog(fmt.Sprintf("kubectl logs -n %s %s -c %s", ns, pod.GetName(), c.Name))
			dumpLog(fmt.Sprintf("kubectl logs -n %s %s -c %s -p", ns, pod.GetName(), c.Name))
		}
	}
}

func dumpLog(cmdStr string) {
	writer.WriteString(fmt.Sprintf("$ %s\n", cmdStr))
	data, err := exec.Command("/bin/sh", "-c", "/usr/local/bin/"+cmdStr).CombinedOutput()
	if err != nil {
		writer.WriteString(err.Error())
	}
	writer.WriteString(string(data))
}
