package client

import (
	"encoding/json"
	"fmt"
	"testing"

	"github.com/juju/errors"
	. "github.com/pingcap/check"
	"github.com/pingcap/schrodinger/pkg/types"
	"github.com/pingcap/schrodinger/util"
	"gopkg.in/h2non/gock.v1"
)

func TestT(t *testing.T) {
	TestingT(t)
}

var _ = Suite(&testTemplateSuite{})

type testTemplateSuite struct {
	newTestTemplate  *types.TestTemplate
	respTestTemplate *types.TestTemplate
}

func (t *testTemplateSuite) SetUpSuite(c *C) {
	t.newTestTemplate = &types.TestTemplate{
		Name:    "test-case-01",
		Creator: "cwen",
		Desc:    "test",
		Source: types.TestSource{
			BinaryName: "test-case-01",
			Type:       types.Latest,
		},
		Status: types.TestTemplateDone,
		Type:   types.GeneralTest,
		ResourceConfig: types.ResourceRequirements{
			Requests: &types.ResourceRequirement{
				CPU:    "2",
				Memory: "4Gi",
			},
			Limits: &types.ResourceRequirement{
				CPU:    "2",
				Memory: "4Gi",
			},
		},
	}

	t.respTestTemplate = new(types.TestTemplate)
	if err := util.Clone(t.respTestTemplate, t.newTestTemplate); err != nil {
		c.Fatal("fail to copy test template")
	}

	t.respTestTemplate.ID = 1
}

func (t *testTemplateSuite) TearDownSuite(c *C) {
	gock.Off()
	c.Assert(gock.IsDone(), Equals, true)
}

func (t *testTemplateSuite) TestCreateTestTemplate(c *C) {
	testAddress := "http://pingcaptest.com"
	cli := NewClient(Config{
		Addr: testAddress,
	})

	mockTestData, _ := json.Marshal(t.newTestTemplate)
	successRespPost := util.Response{
		Code: 200,
		Data: t.respTestTemplate,
	}
	successRespPostData, _ := json.Marshal(successRespPost)

	gock.New(testAddress).
		Post("/tests/templates").
		MatchType("json").
		JSON(mockTestData).
		Reply(200).
		JSON(successRespPostData)

	respTest, err := cli.CreateTestTemplate(t.newTestTemplate)
	c.Assert(err, Equals, nil)
	c.Assert(respTest, DeepEquals, t.respTestTemplate)
}

func (t *testTemplateSuite) TestDeleteTestTemplate(c *C) {
	testAddress := "http://pingcaptestdelete.com"
	cli := NewClient(Config{
		Addr: testAddress,
	})

	successRespDelete := util.Response{
		Code: 200,
		Data: "OK",
	}

	successRespDeleteData, _ := json.Marshal(successRespDelete)

	gock.New(testAddress).
		Delete("/tests/templates/case1/10").
		Reply(200).
		JSON(successRespDeleteData)

	err := cli.DeleteTestTemplate("case1", 10)
	c.Assert(err, Equals, nil)
}

func (t *testTemplateSuite) TestUpdateTestTemplate(c *C) {
	testAddress := "http://pingcaptest.com"
	cli := NewClient(Config{
		Addr: testAddress,
	})

	testCopyForUpdate := new(types.TestTemplate)
	util.Clone(testCopyForUpdate, t.respTestTemplate)

	testCopyForUpdate.Desc = "test bank"
	testCopyForUpdateData, _ := json.Marshal(testCopyForUpdate)

	successRespPut := util.Response{
		Code: 200,
		Data: testCopyForUpdate,
	}

	successRespPutData, _ := json.Marshal(successRespPut)

	gock.New(testAddress).
		Put(fmt.Sprintf("/tests/templates/%s", testCopyForUpdate.Name)).
		MatchType("json").
		JSON(testCopyForUpdateData).
		Reply(200).
		JSON(successRespPutData)

	respTest, err := cli.UpdateTestTemplate(testCopyForUpdate)
	c.Assert(err, Equals, nil)
	c.Assert(respTest, DeepEquals, testCopyForUpdate)
}

func (t *testTemplateSuite) TestSetTestTemplate1(c *C) {
	testAddress := "http://pingcaptest2.com"
	cli := NewClient(Config{
		Addr: testAddress,
	})

	testCopyForSet := new(types.TestTemplate)
	util.Clone(testCopyForSet, t.respTestTemplate)
	testCopyForSet.Desc = "test bank"
	//testCopyForSetData, _ := json.Marshal(testCopyForSet)
	successRespGetLatest := util.Response{
		Code: 200,
		Data: *testCopyForSet,
	}
	successRespPutData, _ := json.Marshal(successRespGetLatest)
	gock.New(testAddress).
		Get(fmt.Sprintf("/tests/templates/%s/latest", testCopyForSet.Name)).
		MatchType("json").
		Reply(200).
		JSON(successRespGetLatest)

	gock.New(testAddress).
		Put(fmt.Sprintf("/tests/templates/%s/%d", testCopyForSet.Name, testCopyForSet.ID)).
		MatchType("json").
		Reply(200).
		JSON(successRespPutData)

	respTest, err := cli.SetTestTemplate(testCopyForSet)
	c.Assert(err, Equals, nil)
	c.Assert(respTest, DeepEquals, testCopyForSet)
}

func (t *testTemplateSuite) TestSetTestTemplate2(c *C) {
	testAddress := "http://pingcaptest3.com"
	cli := NewClient(Config{
		Addr: testAddress,
	})

	testCopyForSet := new(types.TestTemplate)
	util.Clone(testCopyForSet, t.newTestTemplate)

	failGetResp := util.Response{
		Code:    1,
		Message: errors.NotFoundf("case template test-case-02").Error(),
	}
	failRespGetData, _ := json.Marshal(failGetResp)
	gock.New(testAddress).
		Get("/tests/templates/test-case-02").
		Reply(200).
		JSON(failRespGetData)

	testCopyForSet.Name = "test-case-02"
	testPostData, err := json.Marshal(testCopyForSet)

	successRespPost := util.Response{
		Code: 200,
		Data: testCopyForSet,
	}

	successRespPostData, _ := json.Marshal(successRespPost)
	gock.New(testAddress).
		Post("/tests/templates").
		MatchType("json").
		JSON(testPostData).
		Reply(200).
		JSON(successRespPostData)

	respNewTest, err := cli.SetTestTemplate(testCopyForSet)
	c.Assert(err, Equals, nil)
	c.Assert(respNewTest, DeepEquals, testCopyForSet)
}
