package util

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

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

var _ = Suite(&testPatternCloneSuite{})

type testPatternCloneSuite struct {
}

func (t *testPatternCloneSuite) TestMatch(c *C) {
	source, err := ioutil.TempDir("./", "logpattern_test")
	c.Assert(err, IsNil)
	defer os.RemoveAll(source)

	target, err := ioutil.TempDir("./", "logpattern_test")
	c.Assert(err, IsNil)
	defer os.RemoveAll(target)

	sourceStore, err := storage.NewStore(source)
	c.Assert(err, IsNil)
	targetStore, err := storage.NewStore(target)
	c.Assert(err, IsNil)

	expectedPatterns := testGenerateLogPattern(c, sourceStore)
	c.Assert(expectedPatterns, HasLen, 2)
	CloneLogPatternStore(context.Background(), sourceStore, targetStore)

	expectedPatterns2 := make(map[string]*logpattern_go_proto.LogPattern)
	for pos, lg := range expectedPatterns {
		lg2 := CloneLogPattern(lg)
		c.Assert(lg2 != lg, IsTrue)
		c.Assert(lg2, DeepEquals, lg)
		expectedPatterns2[pos] = lg2
	}
	c.Assert(expectedPatterns2, HasLen, 2)

	targetStore.ScanLogPattern(context.Background(), func(key, value []byte) error {
		lg := &logpattern_go_proto.LogPattern{}
		c.Assert(lg.Unmarshal(value), IsNil)
		pos := PosToStr(lg.Pos)

		expect := expectedPatterns2[pos]
		c.Assert(expect, NotNil)
		c.Assert(expect != lg, IsTrue)
		c.Assert(expect, DeepEquals, lg)

		delete(expectedPatterns2, pos)
		return nil
	})
	c.Assert(expectedPatterns2, HasLen, 0)

}

func testGenerateLogPattern(c *C, store *storage.LogPatternStore) map[string]*logpattern_go_proto.LogPattern {
	var patterns = make(map[string]*logpattern_go_proto.LogPattern)

	pattern := &logpattern_go_proto.LogPattern{
		Pos: &logpattern_go_proto.Position{
			PackageInfo: &logpattern_go_proto.Package{
				Repo: "github.com/pingcap/ticdc/dm",
				Tag:  "v4.0.16",
				Hash: "af41784fc3f69fc808b799b845ec99804fa00973",
			},
			FilePath: "dm/dm/master3/config.go",
			Pos: &logpattern_go_proto.CodePosition{
				Line:   159,
				Column: 72743,
			},
			EndPos: &logpattern_go_proto.CodePosition{
				Line:   160,
				Column: 7,
			},
		},
		Func: &logpattern_go_proto.FuncInfo{
			Name: "Toml",
			Pos: &logpattern_go_proto.Position{
				FilePath: "dm/dm/master/config.go",
				Pos: &logpattern_go_proto.CodePosition{
					Line:   154,
					Column: 7140,
				},
				EndPos: &logpattern_go_proto.CodePosition{
					Line:   168,
					Column: 7140,
				},
			},
		},
		Level:     "error",
		Signature: []string{"\"fail to marshal config to toml\"%"},
	}
	patterns[PosToStr(pattern.Pos)] = pattern
	c.Assert(store.WriteLogPattern(context.Background(), pattern), IsNil)

	pattern = &logpattern_go_proto.LogPattern{
		Pos: &logpattern_go_proto.Position{
			PackageInfo: &logpattern_go_proto.Package{
				Repo: "github.com/pingcap/ticdc/dm",
			},
			FilePath: "dm/dm/master4/config.go",
			Pos: &logpattern_go_proto.CodePosition{
				Line:   159,
				Column: 72744,
			},
		},
		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: 7140,
				},
			},
		},
		Level:     "error",
		Signature: []string{"\"fail to marshal config to %%toml\""},
	}
	patterns[PosToStr(pattern.Pos)] = pattern
	c.Assert(store.WriteLogPattern(context.Background(), pattern), IsNil)

	return patterns
}
