package tiem_test

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	tiem2 "github.com/pingcap/endless/testcase/tiem"

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

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

	. "github.com/pingcap/endless/pkg/util"
)

type LoginInfo struct {
	UserName     string `json:"userName"`
	UserPassword string `json:"userPassword"`
}

const (
	UserLoginUrlStr   string = "http://%s-peer.%s.svc:4116/api/v1/user/login"
	UserProfileUrlStr string = "http://%s-peer.%s.svc:4116/api/v1/user/profile"
	UserLogoutUrlStr  string = "http://%s-peer.%s.svc:4116/api/v1/user/logout"
)

var _ = Describe("TiEM", func() {
	Context("while logged in", func() {
		TestCase("should have tenantId", "tiem_user_profile", func() {
			ctx := suiteTestCtx
			tiem := ctx.Resource("tiem").(WorkloadNode)

			url := fmt.Sprintf(UserProfileUrlStr, tiem.Handle().Name, tiem.Handle().Testbed)
			req, err := http.NewRequest("GET", url, nil)
			Expect(err).ShouldNot(HaveOccurred())
			req.Header.Add("accept", "application/json")
			req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))

			client := &http.Client{}
			resp, err := client.Do(req)
			defer resp.Body.Close()
			Expect(err).ShouldNot(HaveOccurred())
			bytes, err := ioutil.ReadAll(resp.Body)
			Expect(err).ShouldNot(HaveOccurred())

			Expect(tiem2.JSONSelector(bytes, "data.userName")).Should(Equal("admin"))
			Expect(tiem2.JSONSelector(bytes, "data.tenantId")).ShouldNot(BeZero())
			Expect(tiem2.JSONSelector(bytes, "data.token")).Should(BeZero())
		})
	})

	Context("while logged out", func() {
		TestCase("can log in and out", "tiem_user_log_in_out", func() {
			token := UserLogin()
			ctx := suiteTestCtx
			tiem := ctx.Resource("tiem").(WorkloadNode)

			url := fmt.Sprintf(UserLogoutUrlStr, tiem.Handle().Name, tiem.Handle().Testbed)
			req, err := http.NewRequest("POST", url, nil)
			Expect(err).ShouldNot(HaveOccurred())
			req.Header.Add("accept", "application/json")
			req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))

			client := &http.Client{}
			resp, err := client.Do(req)
			defer resp.Body.Close()
			Expect(err).ShouldNot(HaveOccurred())
			bodyBytes, err := ioutil.ReadAll(resp.Body)
			Expect(err).ShouldNot(HaveOccurred())

			Expect(tiem2.JSONSelector(bodyBytes, "data.userName")).Should(Equal("admin"))
			Expect(tiem2.JSONSelector(bodyBytes, "data.tenantId")).Should(BeZero())
			Expect(tiem2.JSONSelector(bodyBytes, "data.token")).Should(BeZero())
		})
	})
})

func UserLogin() string {
	ctx := suiteTestCtx
	tiem := ctx.Resource("tiem").(WorkloadNode)

	url := fmt.Sprintf(UserLoginUrlStr, tiem.Handle().Name, tiem.Handle().Testbed)
	loginInfo := LoginInfo{"admin", "admin"}
	loginInfoJson, err := json.Marshal(loginInfo)
	Expect(err).ShouldNot(HaveOccurred())
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(loginInfoJson))
	Expect(err).ShouldNot(HaveOccurred())
	req.Header.Add("accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	defer resp.Body.Close()
	Expect(err).ShouldNot(HaveOccurred())
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	Expect(err).ShouldNot(HaveOccurred())

	Expect(tiem2.JSONSelector(bodyBytes, "data.userName")).Should(Equal("admin"))
	Expect(tiem2.JSONSelector(bodyBytes, "data.tenantId")).Should(BeZero())
	Expect(tiem2.JSONSelector(bodyBytes, "data.token")).ShouldNot(BeZero())
	return fmt.Sprintf("%v", tiem2.JSONSelector(bodyBytes, "data.token"))
}
