package hellolocal_test

import (
	"bytes"
	"fmt"
	"os"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/pingcap/test-infra/sdk/resource"

	_ "github.com/pingcap/endless/pkg/client/tidb"
)

var _ = Describe("Real world test case with local resources", func() {
	It("should pass if you have created your testbed #hello_local_1#", func() {
		ctx := suiteTestCtx

		// Please ensure that you have properly set up the '.env',
		// otherwise the process exits with err "undefined resource: gotpc1".
		//
		// The local WorkloadNode resource is only a handle for you to
		// run commands in your host like in the k8s workloadnode.
		gotpc1 := ctx.Resource("gotpc1").(resource.WorkloadNode)

		// Exec
		stdout, stderr, exitcode, err := gotpc1.Exec(resource.WorkloadNodeExecOptions{Command: `echo "hello from stderr" 1>&2; echo "hello from stdout"`})
		// Assert the err should be nil
		Expect(err).Should(Succeed())
		Expect(stdout).Should(Equal("hello from stdout\n"))
		Expect(stderr).Should(Equal("hello from stderr\n"))
		Expect(exitcode).Should(Equal(0))

		// ExecAsync
		writer := bytes.NewBuffer(make([]byte, 0, 100))
		rcmd, err := gotpc1.ExecAsync(resource.NopCloser(writer), os.Stderr, resource.WorkloadNodeExecOptions{Command: `for i in $(seq 1 5); do echo $i; sleep 0.25; done`})
		Expect(err).Should(Succeed())
		time.Sleep(time.Millisecond * 100)
		for i := 1; i <= 3; i++ {
			n, err := writer.ReadString('\n')
			Expect(err).Should(Succeed())
			Expect(n).Should(Equal(fmt.Sprintf("%d\n", i)))
			time.Sleep(time.Millisecond * 250)
		}
		errCmd := rcmd.Wait()
		Expect(writer.String()).Should(Equal("4\n5\n"))
		Expect(errCmd.Err).Should(Succeed())
		Expect(errCmd.ExitCode).Should(Equal(0))

		// ExecAsyncInterruptible
		writer = bytes.NewBuffer(make([]byte, 0, 100))
		rcmdI, err := gotpc1.ExecAsyncInterruptible(resource.NopCloser(writer), resource.WorkloadNodeExecOptions{Command: `for i in $(seq 1 5); do echo $i; sleep 0.25; done`})
		Expect(err).Should(Succeed())
		go func() {
			time.Sleep(time.Millisecond * 800)
			err = rcmdI.Interrupt()
		}()
		time.Sleep(time.Millisecond * 100)
		for i := 1; i <= 3; i++ {
			n, err := writer.ReadString('\n')
			Expect(err).Should(Succeed())
			Expect(n).Should(Equal(fmt.Sprintf("%d\n", i)))
			time.Sleep(time.Millisecond * 250)
		}

		errCmd = rcmdI.Wait()
		Expect(errCmd.Err).Should(MatchError("signal: terminated"))
		Expect(writer.String()).Should(Equal("4\n"))
		Expect(errCmd.ExitCode).Should(Equal(-1))
		Expect(errCmd.Err.Error()).Should(Equal("signal: terminated"))
	})

	Context("assume that you have created your testbed", func() {
		It("should pass if you have setup your MYSQL_PROXY correctly #hello_local_2#", func() {
			ctx := suiteTestCtx
			tc := ctx.Resource("tc1").(resource.TiDBCluster)

			// Please ensure that you have setup .env properly,

			// Setup a sql.DB instance
			_, err := tc.GetDB("test")
			// Assert the err should be nil
			Expect(err).Should(Succeed())
		})
	})
})
