package main

import (
	"context"
	"errors"
	"sync"
	"time"

	pdClient "github.com/pingcap/pd/client"
	client "github.com/pingcap/schrodinger/pkg/test_client"
)

// ErrBadTSO tso fallback error.
var ErrBadTSO = errors.New("tso fallback")

func verifyTSO(ctx context.Context, pds []string) error {
	cli, err := pdClient.NewClient(pds, pdClient.SecurityOption{})
	if err != nil {
		return nil
	}
	reqCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()
	lastPhysical, lastLogic := int64(0), int64(0)
	for i := 0; i < 10; i++ {
		p, l, err := cli.GetTS(reqCtx)
		if err != nil {
			return nil
		}
		if p > lastPhysical || p == lastPhysical && l > lastLogic {
			lastPhysical, lastLogic = p, l
		} else {
			return ErrBadTSO
		}
	}

	return nil
}

func checkTSO(ctx context.Context, cli *client.Client, wg *sync.WaitGroup) {
	ticker := time.NewTicker(checkInterval)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-ctx.Done():
				return
			case <-ticker.C:
				pds := cli.PDs()
				err := verifyTSO(ctx, pds)
				if err != nil {
					client.Fatalf("[pd test - check TSO] meets error: %s", err)
				}
			}
		}
	}()
}
