package storage

import (
	"reflect"

	"github.com/juju/errors"
	. "github.com/pingcap/check"
	"github.com/pingcap/schrodinger/pkg/types"
)

var _ = Suite(&TidbClusterConfigSuite{})

type TidbClusterConfigSuite struct {
	store *Storage
}

func (t *TidbClusterConfigSuite) SetUpTest(c *C) {
	t.store = setupStore("tidbClusterConfig")
}

func (t *TidbClusterConfigSuite) TearDownSuite(c *C) {
	t.store.Close()
}

func (t *TidbClusterConfigSuite) TestCreateTiDBClusterConfigTemplate(c *C) {
	if err := t.store.CreateTiDBClusterConfigTemplate(insertTiDBClusterConfigTemplate); err != nil {
		c.Fatal("creating tiDBClusterConfigTemplate fails:", errors.ErrorStack(err))
	}
	tiDBClusterConfigTemplates := t.store.ListTiDBClusterConfigTemplates()
	if len(tiDBClusterConfigTemplates) != 1 {
		c.Fatalf("expect one element in tiDBClusterConfigTemplates, got %v", tiDBClusterConfigTemplates)
	}
	got := tiDBClusterConfigTemplates[0]

	if !reflect.DeepEqual(insertTiDBClusterConfigTemplate, got) {
		c.Fatalf("expect %v, got %v", *insertTiDBClusterConfigTemplate, *got)
	}
}

func (t *TidbClusterConfigSuite) TestUpdateTiDBClusterConfigTemplate(c *C) {
	t.TestCreateTiDBClusterConfigTemplate(c)

	updateTiDBClusterConfigTemplate.ID = insertTiDBClusterConfigTemplate.ID
	updateTiDBClusterConfigTemplate.Ctime = insertTiDBClusterConfigTemplate.Ctime

	if err := t.store.UpdateTiDBClusterConfigTemplate(updateTiDBClusterConfigTemplate); err != nil {
		c.Fatalf("updating tidb cluster config template fails: %s", errors.ErrorStack(err))
	}

	tiDBClusterConfigTemplates := t.store.ListTiDBClusterConfigTemplates()
	if len(tiDBClusterConfigTemplates) != 1 {
		c.Fatalf("expect one element in tiDBClusterConfigTemplates, got %v", tiDBClusterConfigTemplates)
	}
	got := tiDBClusterConfigTemplates[0]

	if !reflect.DeepEqual(updateTiDBClusterConfigTemplate, got) {
		c.Fatalf("expect %v, got %v", *updateTiDBClusterConfigTemplate, *got)
	}
}

func (t *TidbClusterConfigSuite) TestDeleteTiDBClusterConfigTemplate(c *C) {
	t.TestCreateTiDBClusterConfigTemplate(c)

	if err := t.store.DeleteTiDBClusterConfigTemplate(insertTiDBClusterConfigTemplate.ID); err != nil {
		c.Fatalf("delete tidb cluster config template fails: %s", errors.ErrorStack(err))
	}

	tiDBClusterConfigTemplates := t.store.ListTiDBClusterConfigTemplates()
	if len(tiDBClusterConfigTemplates) != 0 {
		c.Fatalf("expect zero element in tiDBClusterConfigTemplates, got %v", tiDBClusterConfigTemplates)
	}

	if err := t.store.DeleteTiDBClusterConfigTemplate(insertTiDBClusterConfigTemplate.ID); !errors.IsNotFound(err) {
		c.Fatalf("expect not found error, got %v", err)
	}
}

func (t *TidbClusterConfigSuite) TestListTiDBClusterConfigTemplates(c *C) {
	tiDBClusterConfigTemplates := t.store.ListTiDBClusterConfigTemplates()
	if len(tiDBClusterConfigTemplates) != 0 {
		c.Fatalf("expect zero elements, found %v", tiDBClusterConfigTemplates)
	}

	t.TestCreateTiDBClusterConfigTemplate(c)
}

func (t *TidbClusterConfigSuite) TestGetTiDBClusterConfigTemplateByID(c *C) {
	t.TestCreateTiDBClusterConfigTemplate(c)

	got, exists := t.store.GetTiDBClusterConfigTemplate(insertTiDBClusterConfigTemplate.ID)
	c.Assert(exists, Equals, true)

	if !reflect.DeepEqual(insertTiDBClusterConfigTemplate, got) {
		c.Fatalf("expect %v, got %v", insertTiDBClusterConfigTemplate, got)
	}

	_, exists = t.store.GetTiDBClusterConfigTemplate(1234567)
	c.Assert(exists, Equals, false)
}

func (t *TidbClusterConfigSuite) TestGetTiDBClusterConfigTemplateByName(c *C) {
	t.TestCreateTiDBClusterConfigTemplate(c)

	got, exists := t.store.GetTiDBClusterConfigTemplateByName(insertTiDBClusterConfigTemplate.Name)
	c.Assert(exists, Equals, true)

	if !reflect.DeepEqual(insertTiDBClusterConfigTemplate, got) {
		c.Fatalf("expect %v, got %v", insertTiDBClusterConfigTemplate, got)
	}

	_, exists = t.store.GetTiDBClusterConfigTemplateByName("1234567")
	c.Assert(exists, Equals, false)
}

func (t *TidbClusterConfigSuite) TestGetTiDBClusterConfigTemplatesByTag(c *C) {
	tiDBClusterConfigTemplates := t.store.GetTiDBClusterConfigTemplateByTag(insertTiDBClusterConfigTemplate.Tag)
	if len(tiDBClusterConfigTemplates) != 0 {
		c.Fatalf("expect zero elements, found %v", tiDBClusterConfigTemplates)
	}

	t.TestCreateTiDBClusterConfigTemplate(c)

	tiDBClusterConfigTemplates = t.store.GetTiDBClusterConfigTemplateByTag(insertTiDBClusterConfigTemplate.Tag)
	if len(tiDBClusterConfigTemplates) != 1 {
		c.Fatalf("expect one elements, found %v", tiDBClusterConfigTemplates)
	}
	got := tiDBClusterConfigTemplates[0]

	if !reflect.DeepEqual(insertTiDBClusterConfigTemplate, got) {
		c.Fatalf("expect %v, got %v", *insertTiDBClusterConfigTemplate, *got)
	}
}

var insertTiDBClusterConfigTemplate = &types.TiDBClusterConfigTemplate{
	Name:        "name",
	Tag:         "tag",
	Description: "description",
	Content:     "content",
	IsDeleted:   false,
}

var updateTiDBClusterConfigTemplate = &types.TiDBClusterConfigTemplate{
	Name:        "name 2",
	Tag:         "tag 2",
	Description: "description 2",
	Content:     "content 2",
	IsDeleted:   false,
}
