package steps

import (
	"context"
	"fmt"
	"time"

	"github.com/pingcap/errors"
	"github.com/pingcap/log"
	apiresouce "github.com/pingcap/test-infra/common/model/resource"
	"github.com/pingcap/test-infra/sdk/resource"
	"go.uber.org/zap"
)

type pdSwitchLeader struct {
}

func (s *pdSwitchLeader) Execute(ctx context.Context) error {
	tc, err := GetInner(ctx).Board().TiDBCluster()
	if err != nil {
		return err
	}

	client, err := tc.PDClient()
	if err != nil {
		return err
	}

	members, err := client.GetMembers()
	if err != nil {
		log.Error("get pd members failed", zap.Error(err))
		return errors.Trace(err)
	}

	log.Info("pd leader", zap.String("leader-name", members.Leader.Name))
	var targetName string
	for _, member := range members.Members {
		if member.MemberID != members.Leader.MemberID {
			targetName = member.Name
			break
		}
	}

	if err := client.TransferPDLeader(targetName); err != nil {
		log.Error("transfer pd leader failed", zap.Error(err))
		return errors.Trace(err)
	}

	log.Info("transfer pd leader success", zap.String("leader-name", targetName))

	return nil
}

func (s *pdSwitchLeader) String() string {
	return fmt.Sprintf("pdSwitchLeader")
}

func NewPdSwitchLeader() Step {
	return &pdSwitchLeader{}
}

type pdNetworkLatency struct {
	duration time.Duration
	latency  string
	jitter   string
	target   *apiresouce.ResourceHandle
}

func NewPDNetworkLatency(target *apiresouce.ResourceHandle, duration time.Duration, latency, jitter string) *pdNetworkLatency {
	return &pdNetworkLatency{
		target:   target,
		duration: duration,
		latency:  latency,
		jitter:   jitter,
	}
}

func (s *pdNetworkLatency) Execute(ctx context.Context) error {
	selectOption := resource.TiDBClusterSelectorOpts{
		TiDBClusterPDSelectorSpec: &resource.TiDBClusterPDSelectorSpec{
			IsLeader: &[]bool{true, false}[0],
		},
	}
	return newNetworkLatencyChaosTask(
		s.target,
		selectOption,
		s.duration, s.latency, s.jitter).Execute(ctx)
}

func (s *pdNetworkLatency) String() string {
	return fmt.Sprintf("randomCDCNetworkLatency: duration=%+v, latency=%+v, jitter=%+v",
		s.duration, s.latency, s.jitter)
}
