package plugin

import (
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"

	"github.com/tidbcloud/infra-provider/pkg/config"
)

var (
	_ FilterPlugin = &FakePlugin{}
	_ ScorePlugin  = &FakePlugin{}
)

func NewFakePluginFactory(name string) Factory {
	return func(cfg config.AcctSchedPluginConfig) (Plugin, error) {
		return &FakePlugin{PluginName: name}, nil
	}
}

type FakePlugin struct {
	PluginName    string
	PreFilterFunc func(ctx *SchedContext, network *cloudv1.Network, accts []*cloudv1.Account) *ActionResult
	FilterFunc    func(*SchedContext, *cloudv1.Network, *cloudv1.Account) *ActionResult
	ScoreFunc     func(*SchedContext, *cloudv1.Network, []*cloudv1.Account) ([]AcctScore, *ActionResult)
}

func (p *FakePlugin) Name() string {
	return p.PluginName
}

func (p *FakePlugin) PreFilter(ctx *SchedContext, network *cloudv1.Network, accts []*cloudv1.Account) *ActionResult {
	if p.PreFilterFunc != nil {
		return p.PreFilterFunc(ctx, network, accts)
	}
	return NewActionResult(Error, "prefilter failed by default")
}

func (p *FakePlugin) Filter(ctx *SchedContext, network *cloudv1.Network, acct *cloudv1.Account) *ActionResult {
	if p.FilterFunc != nil {
		return p.FilterFunc(ctx, network, acct)
	}
	return NewActionResult(Error, "filter failed by default")
}

func (p *FakePlugin) Score(ctx *SchedContext, network *cloudv1.Network, accts []*cloudv1.Account) ([]AcctScore, *ActionResult) {
	if p.ScoreFunc != nil {
		return p.ScoreFunc(ctx, network, accts)
	}
	return nil, NewActionResult(Error, "score failed by default")
}

// SetScoreFuncAsSuccess returns the success
func (p *FakePlugin) SetPreFilterFuncAsSuccess() {
	p.PreFilterFunc = func(sc *SchedContext, n *cloudv1.Network, accts []*cloudv1.Account) *ActionResult {
		return NewActionResult(Success)
	}
}

// SetFilterFuncAsSuccess returns the success for all accounts
func (p *FakePlugin) SetFilterFuncAsSuccess() {
	p.FilterFunc = func(sc *SchedContext, n *cloudv1.Network, a *cloudv1.Account) *ActionResult {
		return NewActionResult(Success)
	}
}

// SetScoreFunc returns a default score for all accounts
func (p *FakePlugin) SetScoreFunc(score int64) {
	p.ScoreFunc = func(sc *SchedContext, n *cloudv1.Network, accts []*cloudv1.Account) ([]AcctScore, *ActionResult) {
		var scores []AcctScore
		for _, acct := range accts {
			scores = append(scores, AcctScore{
				AccountName: acct.Name,
				Score:       score,
			})
		}
		return scores, NewActionResult(Success)
	}
}
