package lightning

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/suite"
)

type mockListObjsSuite struct {
	suite.Suite
}

func TestMockListObjsSuite(t *testing.T) {
	suite.Run(t, new(mockListObjsSuite))
}

func (s *mockListObjsSuite) TestGenerateFileList() {
	type testCase struct {
		Prefix         string
		Setting        *mockDataSourceSetting
		ExpectFileList []string
	}
	for _, tc := range []testCase{
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						Suffix:        "sql",
						DataFileCount: 3,
					},
				},
			},
			ExpectFileList: []string{
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db01.tbl01.00000000.sql",
				"dir/db01.tbl01.00000001.sql",
				"dir/db01.tbl01.00000002.sql",
			},
		},
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						Suffix:        "sql",
						DataFileCount: 3,
					},
					{
						DBName:        "db01",
						TableName:     "tbl02",
						Suffix:        "sql",
						DataFileCount: 1,
					},
				},
			},
			ExpectFileList: []string{
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db01.tbl01.00000000.sql",
				"dir/db01.tbl01.00000001.sql",
				"dir/db01.tbl01.00000002.sql",
				"dir/db01.tbl02-schema.sql",
				"dir/db01.tbl02.00000000.sql",
			},
		},
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						Suffix:        "sql",
						DataFileCount: 1,
					},
					{
						DBName:        "db02",
						TableName:     "tbl01",
						Suffix:        "sql",
						DataFileCount: 3,
					},
					{
						DBName:        "db02",
						TableName:     "tbl02",
						Suffix:        "csv",
						DataFileCount: 1,
					},
				},
			},
			ExpectFileList: []string{
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db01.tbl01.00000000.sql",
				"dir/db02-schema-create.sql",
				"dir/db02.tbl01-schema.sql",
				"dir/db02.tbl01.00000000.sql",
				"dir/db02.tbl01.00000001.sql",
				"dir/db02.tbl01.00000002.sql",
				"dir/db02.tbl02-schema.sql",
				"dir/db02.tbl02.00000000.csv",
			},
		},
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						DataFileCount: 2,
						CustomDataFileNameGen: func(dbName string, tblName string, idx int, suffix string) string {
							if idx < 1 {
								return fmt.Sprintf("aaa.%d.csv", idx)
							} else {
								return fmt.Sprintf("zzz.%d.csv", idx)
							}
						},
					},
					{
						DBName:        "db02",
						TableName:     "tbl01",
						Suffix:        "sql",
						DataFileCount: 3,
					},
				},
			},
			ExpectFileList: []string{
				"dir/aaa.0.csv",
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db02-schema-create.sql",
				"dir/db02.tbl01-schema.sql",
				"dir/db02.tbl01.00000000.sql",
				"dir/db02.tbl01.00000001.sql",
				"dir/db02.tbl01.00000002.sql",
				"dir/zzz.1.csv",
			},
		},
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						DataFileCount: 2,
						Suffix:        "csv",
					},
				},
				IgnoreFileSetting: &ignoreFileSetting{
					IgnoreFileCount: 3,
				},
			},
			ExpectFileList: []string{
				"dir/.ignore-00000000",
				"dir/.ignore-00000001",
				"dir/.ignore-00000002",
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db01.tbl01.00000000.csv",
				"dir/db01.tbl01.00000001.csv",
			},
		},
		{
			Prefix: "dir",
			Setting: &mockDataSourceSetting{
				TableSettings: []*mockTableSetting{
					{
						DBName:        "db01",
						TableName:     "tbl01",
						DataFileCount: 2,
						Suffix:        "csv",
					},
				},
				IgnoreFileSetting: &ignoreFileSetting{
					IgnoreFileCount: 3,
					IgnoreFileNameGen: func(idx int) string {
						if idx < 2 {
							return fmt.Sprintf("aaa-%d", idx)
						} else {
							return fmt.Sprintf("zzz-%d", idx)
						}
					},
				},
			},
			ExpectFileList: []string{
				"dir/aaa-0",
				"dir/aaa-1",
				"dir/db01-schema-create.sql",
				"dir/db01.tbl01-schema.sql",
				"dir/db01.tbl01.00000000.csv",
				"dir/db01.tbl01.00000001.csv",
				"dir/zzz-2",
			},
		},
	} {
		s.Require().Equal(tc.ExpectFileList, generateFileList(tc.Prefix, tc.Setting))
	}
}

func (s *mockListObjsSuite) TestGetStartIndex() {
	testFileList := []string{
		"a1", "a2",
		"b1", "b2",
		"c1", "c2",
		"z1", "z2",
	}
	type testCase struct {
		StartKey    string
		ExpectIndex int
	}
	for _, tc := range []testCase{
		{
			StartKey:    ".",
			ExpectIndex: 0,
		},
		{
			StartKey:    "a",
			ExpectIndex: 0,
		},
		{
			StartKey:    "a1",
			ExpectIndex: 1,
		},
		{
			StartKey:    "a~",
			ExpectIndex: 2,
		},
		{
			StartKey:    "b~",
			ExpectIndex: 4,
		},
		{
			StartKey:    "b2",
			ExpectIndex: 4,
		},
		{
			StartKey:    "c",
			ExpectIndex: 4,
		},
		{
			StartKey:    "c1",
			ExpectIndex: 5,
		},
		{
			StartKey:    "c~",
			ExpectIndex: 6,
		},
		{
			StartKey:    "zzz",
			ExpectIndex: 8,
		},
	} {
		s.Require().Equal(tc.ExpectIndex, getStartIndex(testFileList, tc.StartKey))
	}
}
