// Copyright 2021 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package functionality

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/pingcap/endless/pkg/matcher"
	. "github.com/pingcap/endless/pkg/workload"
	. "github.com/pingcap/endless/testcase/geopartition/utils"
)

func sequenceTest(ctx *SuiteContext) {
	It("Sequence should work on placement tables", func() {
		defer func() {
			MustExec(ctx.DB, "DROP SEQUENCE IF EXISTS seq")
			MustExec(ctx.DB, "DROP TABLE IF EXISTS t1,t2")
			MustExec(ctx.DB, "DROP PLACEMENT POLICY IF EXISTS p1")
			MustExec(ctx.DB, "DROP PLACEMENT POLICY IF EXISTS p2")
		}()

		MustExec(ctx.DB, "DROP SEQUENCE IF EXISTS seq")
		MustExec(ctx.DB, "DROP TABLE IF EXISTS t1,t2")
		MustExec(ctx.DB, "DROP PLACEMENT POLICY IF EXISTS p1")
		MustExec(ctx.DB, "DROP PLACEMENT POLICY IF EXISTS p2")

		MustExec(ctx.DB, "CREATE SEQUENCE seq")
		MustExec(ctx.DB, "CREATE PLACEMENT POLICY p1 FOLLOWERS=4")
		MustExec(ctx.DB, "CREATE PLACEMENT POLICY p2 LEADER_CONSTRAINTS=\"[+region=us-east-1]\" FOLLOWER_CONSTRAINTS=\"[+region=us-east-2]\" FOLLOWERS=1")
		MustExec(ctx.DB, "CREATE TABLE t1 (a int default next value for seq) PLACEMENT POLICY p1")
		MustExec(ctx.DB, "CREATE TABLE t2 (a int default next value for seq) PLACEMENT POLICY p2")

		MustExec(ctx.DB, "INSERT INTO t1 values()")
		MustExec(ctx.DB, "INSERT INTO t1 values()")
		MustExec(ctx.DB, "INSERT INTO t2 values()")
		MustExec(ctx.DB, "INSERT INTO t2 values()")

		rows := ReadAll(MustQuery(ctx.DB, "select * from t1"))
		Expect(rows).Should(Equal([][]string{{"1"}, {"2"}}))

		rows = ReadAll(MustQuery(ctx.DB, "select * from t2"))
		Expect(rows).Should(Equal([][]string{{"3"}, {"4"}}))

		Try(WaitScheduled(ctx.DB, "t1", time.Minute))
		Try(WaitScheduled(ctx.DB, "t2", time.Minute))
		// wait local cache updated
		CheckRegions(ctx, "t1", "", func(r Regions) {
			r.CheckLeaderPlacement("").
				CheckFollowerPlacement("", 4).
				CheckNoPeersLeft()
		})
		CheckRegions(ctx, "t2", "", func(r Regions) {
			r.CheckLeaderPlacement("+region=us-east-1").
				CheckFollowerPlacement("+region=us-east-2", 1).
				CheckNoPeersLeft()
		})
	})
}
