package storage

import (
	"testing"
	"time"

	"github.com/ngaut/log"
	. "github.com/pingcap/check"
	"github.com/pingcap/schrodinger/pkg/types"
	"github.com/pingcap/schrodinger/util"
)

var _ = Suite(&catProcessSuite{})

type catProcessSuite struct {
	store *Storage
}

func (t *catProcessSuite) SetUpSuite(c *C) {
	t.store = setupStore("catProcess")
}

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

var catProcess = &types.CatProcess{
	Owner:          "box-1",
	Creator:        "cwen",
	BoxID:          1,
	BoxName:        "box-1",
	ExperimentName: "experiment-1",
	Name:           "test-1",
	Namespace:      "namespace-1",
	Destroyed:      false,
	Config: types.TiDBClusterConfig{
		PDConfig: types.ComponentConfig{
			Size:     3,
			LogLevel: "Debug",
		},
	},
	RunVersion: types.RunVersion{
		TiDBVersion: types.VersionInfo{
			Name:      "tidb",
			Type:      "branch",
			Value:     "master",
			BuildTime: time.Now().Format(util.TimeFormat),
		},
	},
	State:        types.CatStateNormal,
	Stage:        types.CatStageNew,
	Report:       &types.CatReport{},
	IgnoreLabels: make(map[string]string),
	BackupName:   "test-backup-1",
	Meta: &types.Meta{
		Labels: map[string]string{
			"node": "bench",
			"idc":  "idc",
		},
	},
}

func (t *catProcessSuite) TestCatProcess(c *C) {
	cps, _ := t.store.ListCatProcess(nil)
	c.Assert(len(cps), Equals, 0)

	cp := &types.CatProcess{}
	err := util.Clone(cp, catProcess)
	c.Assert(err, Equals, nil)

	// test for CreateCatProcess
	err = t.store.CreateCatProcess(cp)
	if err != nil {
		log.Error(err)
	}
	c.Assert(err, Equals, nil)

	cp1, ok := t.store.GetCatProcess(cp.ID)
	c.Assert(ok, Equals, true)
	c.Assert(cp1, DeepEquals, cp)

	cp.Creator = "cwen0"
	cp.Stage = types.CatStageCreating
	err = t.store.UpdateCatProcess(cp)
	if err != nil {
		log.Error(err)
	}
	c.Assert(err, Equals, nil)

	cp1, ok = t.store.GetCatProcessByName(cp.Name)
	c.Assert(ok, Equals, true)
	c.Assert(cp1, DeepEquals, cp)

	cps, _ = t.store.ListCatProcess(nil)
	c.Assert(len(cps), Equals, 1)

	cp2 := &types.CatProcess{}
	err = util.Clone(cp2, catProcess)
	c.Assert(err, Equals, nil)

	time.Sleep(2 * time.Second)
	cp2.Name = "test-2"
	err = t.store.CreateCatProcess(cp2)
	if err != nil {
		log.Error(err)
	}
	c.Assert(err, Equals, nil)
	cps, _ = t.store.ListCatProcess(nil)
	c.Assert(len(cps), Equals, 2)

	cp2.Stage = types.CatStageUpdating
	cp2.BackupName = ""
	time.Sleep(1 * time.Second)
	err = t.store.UpdateCatProcess(cp2)
	c.Assert(err, Equals, nil)
	cps, _ = t.store.ListCatProcess(nil)
	c.Assert(len(cps), Equals, 2)
	c.Assert(cps[0], DeepEquals, cp2)
	c.Assert(cps[1], DeepEquals, cp)
}

func TestGenCatProcessListStmt(t *testing.T) {
	got := genCatProcessListStmt(nil)
	expect := stmtCatProcessQueryBase + `WHERE 1 = 1
ORDER BY create_time DESC
`
	if got != expect {
		t.Fatalf("expect %s, got %s", expect, got)
	}

	got = genCatProcessListStmt(&CatProcessConditions{})
	expect = stmtCatProcessQueryBase + `WHERE 1 = 1
ORDER BY create_time DESC
`
	if got != expect {
		t.Fatalf("expect %s, got %s", expect, got)
	}

	got = genCatProcessListStmt(&CatProcessConditions{Names: []string{"hi", "hello"}, Limit: 10, Offset: 10})
	expect = stmtCatProcessQueryBase + `WHERE 1 = 1 AND name LIKE '%hi%'
ORDER BY create_time DESC
LIMIT 10 OFFSET 10
`
	if got != expect {
		t.Fatalf("expect %s, got %s", expect, got)
	}

	got = genCatProcessListStmt(&CatProcessConditions{Names: []string{"hi", "hello"}})
	expect = stmtCatProcessQueryBase + `WHERE 1 = 1 AND name LIKE '%hi%'
ORDER BY create_time DESC
`
	if got != expect {
		t.Fatalf("expect %s, got %s", expect, got)
	}
}
