package storage

import (
	"context"
	"io/ioutil"
	"os"
	"testing"

	logpattern_go_proto "github.com/pingcap-inc/alioth/proto"
	"github.com/pingcap-inc/alioth/storage/keyvalue"
	. "github.com/pingcap/check"
)

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

var _ = Suite(&testKeyValueSuite{})

type testKeyValueSuite struct {
}

func (t *testKeyValueSuite) TestKeyValue(c *C) {
	tmpdir, err := ioutil.TempDir("./", "logpattern_test")
	c.Assert(err, IsNil)
	defer os.RemoveAll(tmpdir)

	store, err := NewStore(tmpdir)
	c.Assert(err, IsNil)

	// test log pattern
	pattern := &logpattern_go_proto.LogPattern{
		Pos: &logpattern_go_proto.Position{
			PackageInfo: &logpattern_go_proto.Package{
				Repo: "github.com/pingcap/ticdc/dm",
			},
			FilePath: "dm/dm/master3/config.go",
			Pos: &logpattern_go_proto.CodePosition{
				Line:   154,
				Column: 7274,
			},
			EndPos: &logpattern_go_proto.CodePosition{
				Line:   154,
				Column: 7280,
			},
		},
		Func: &logpattern_go_proto.FuncInfo{
			Name: "Toml",
			Pos: &logpattern_go_proto.Position{
				FilePath: "dm/dm/master/config.go",
				Pos: &logpattern_go_proto.CodePosition{
					Line:   138,
					Column: 7144,
				},
				EndPos: &logpattern_go_proto.CodePosition{
					Line:   168,
					Column: 1,
				},
			},
		},
		Level:     "error",
		Signature: []string{"\"fail to marshal config to % wwwww"},
	}

	err = store.WriteLogPattern(context.Background(), pattern)
	c.Assert(err, IsNil)

	retPattern := &logpattern_go_proto.LogPattern{}
	err = store.ScanLogPattern(context.Background(), func(_, value []byte) error {
		return retPattern.Unmarshal(value)
	})
	c.Assert(err, IsNil)
	c.Assert(retPattern, DeepEquals, pattern)

	// write error log pattern
	patternKey, err := keyvalue.EncodeLogKey(pattern.Pos)
	c.Assert(err, IsNil)
	wr, err := store.db.Writer(context.Background())
	c.Assert(err, IsNil)
	err = wr.Write(patternKey, []byte("xxx"))
	c.Assert(err, IsNil)
	c.Assert(wr.Close(), IsNil)

	err = store.ScanLogPattern(context.Background(), func(_, value []byte) error {
		return retPattern.Unmarshal(value)
	})
	c.Assert(err, NotNil)

	// test log coverage
	coverage := &logpattern_go_proto.Coverage{
		Pos: &logpattern_go_proto.Position{
			PackageInfo: &logpattern_go_proto.Package{
				Repo: "github.com/pingcap/ticdc/dm",
			},
			FilePath: "dm/dm/master3/config.go",
			Pos: &logpattern_go_proto.CodePosition{
				Line:   154,
				Column: 7274,
			},
			EndPos: &logpattern_go_proto.CodePosition{
				Line:   154,
				Column: 7280,
			},
		},
		CovCount: 32,
		CovCountByLog: map[string]int32{
			"xxx": 32,
		},
	}

	err = store.WriteLogCoverage(context.Background(), coverage)
	c.Assert(err, IsNil)

	retCoverage := &logpattern_go_proto.Coverage{}
	err = store.ScanLogCoverage(context.Background(), func(_, value []byte) error {
		return retCoverage.Unmarshal(value)
	})
	c.Assert(err, IsNil)
	c.Assert(retCoverage, DeepEquals, coverage)

	// write error log coverage
	coverageKey, err := keyvalue.EncodeCoverageKey(coverage.Pos)
	c.Assert(err, IsNil)
	wr, err = store.db.Writer(context.Background())
	c.Assert(err, IsNil)
	err = wr.Write(coverageKey, []byte("xxx"))
	c.Assert(err, IsNil)
	c.Assert(wr.Close(), IsNil)

	err = store.ScanLogCoverage(context.Background(), func(_, value []byte) error {
		return retCoverage.Unmarshal(value)
	})
	c.Assert(err, NotNil)
}
