package storage

import (
	"reflect"

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

var _ = Suite(&endpointSuite{})

type endpointSuite struct {
	store *Storage
}

func (t *endpointSuite) SetUpTest(c *C) {
	t.store = setupStore("endpoint")
}

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

func (t *endpointSuite) TestCreateEndpoint(c *C) {
	if err := t.store.CreateEndpoint(insertEndpoint); err != nil {
		c.Fatal("creating endpoint fails:", errors.ErrorStack(err))
	}
	if insertEndpoint.ID == 0 {
		c.Fatal("expect non zero ID")
	}

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

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

func (t *endpointSuite) TestUpdateEndpoint(c *C) {
	t.TestCreateEndpoint(c)

	updateEndpoint.ID = insertEndpoint.ID
	updateEndpoint.Ctime = insertEndpoint.Ctime

	if err := t.store.UpdateEndpoint(updateEndpoint); err != nil {
		c.Fatal("updating endpoint fails:", err)
	}
	endpoints := t.store.ListEndpoint()
	if len(endpoints) != 1 {
		c.Fatalf("expect one element, got %v", endpoints)
	}
	got := endpoints[0]

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

func (t *endpointSuite) TestListEndpoint(c *C) {
	t.TestCreateEndpoint(c)

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

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

func (t *endpointSuite) TestGetEndpoint(c *C) {
	t.TestCreateEndpoint(c)

	got, exists := t.store.GetEndpoint(insertEndpoint.ID)
	c.Assert(exists, Equals, true)

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

	got, exists = t.store.GetEndpoint(1234567)
	c.Assert(exists, Equals, false)
}

func (t *endpointSuite) TestDetectDuplicateEndpoint(c *C) {

	t.TestCreateEndpoint(c)

	got, exists := t.store.detectDuplicateEndpoint(insertEndpoint.Name, insertEndpoint.Type)
	c.Assert(exists, Equals, true)
	if !reflect.DeepEqual(insertEndpoint, got) {
		c.Fatalf("expect %v, got %v", *insertEndpoint, *got)
	}
}

func (t *endpointSuite) TestDeleteEndpoint(c *C) {
	t.TestCreateEndpoint(c)

	if err := t.store.DeleteEndpoint(insertEndpoint.ID); err != nil {
		c.Fatal("deleting endpoint fails:", errors.ErrorStack(err))
	}

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

var insertEndpoint = &types.Endpoint{
	Meta: &types.Meta{
		Labels: map[string]string{"node": "idc"},
	},
	Type:  "type",
	Name:  "name",
	Value: "value",
}

var updateEndpoint = &types.Endpoint{
	Meta: &types.Meta{
		Labels: map[string]string{"node": "idc-2"},
	},
	Type:  "type 2",
	Name:  "name 2",
	Value: "value 2",
}
