package box

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/pkg/storage"
	"github.com/pingcap/schrodinger/pkg/types"
	"github.com/pingcap/schrodinger/util"
)

func boxToExperiment(box *types.Box, store *storage.Storage) (*types.ExperimentProcess, error) {
	id := util.UniqID()
	experiment := &types.ExperimentProcess{
		ID:       id,
		State:    types.ExperimentStateNormal,
		Stage:    types.ExperimentStagePending,
		BoxID:    box.ID,
		BoxName:  box.Name,
		Creator:  box.Creator,
		Meta:     &types.Meta{},
		CatCount: 0,
		Tests:    make(map[string]*types.TestProcess),
	}

	tc := &types.TestsConfig{
		InOrder:  box.Tests.InOrder,
		LabelStr: box.Tests.LabelStr,
	}

	for _, t := range box.Tests.Tests {
		ns := strings.Split(t.TestName, ":")
		if len(ns) < 1 {
			log.Errorf("%s not validate", t.TestName)
			continue
		}

		te := types.TestConfig{
			TestName:       ns[0],
			TestTemplateID: t.TestTemplateID,
			OverrideArgs:   t.OverrideArgs,
		}
		tc.Tests = append(tc.Tests, te)
	}

	experiment.Config = &types.ExperimentConfig{
		WithoutCat: box.WithoutCat,
		Cat:        box.Cat,
		Tests:      tc,
		Misc:       box.Misc,
	}

	index, err := store.GetBoxExperimentCount(box.ID)
	if err != nil {
		return nil, errors.Trace(err)
	}

	experiment.BoxIndex = index + 1
	experiment.Name = util.GenExperimentName(box.Name, experiment.BoxIndex)
	experiment.Namespace = util.GenExperimentNamespace(experiment.Name)

	return experiment, nil
}

func triggerBox(ctrl *Controller, boxID int64) error {
	box, exist := ctrl.storage.GetBox(boxID)
	if !exist {
		return errors.NotFoundf("box %d", boxID)
	}

	experimentProcess, err := boxToExperiment(box, ctrl.storage)
	if err != nil {
		return errors.Trace(err)
	}

	log.Infof("trigger build experiment %d by box %d", experimentProcess.ID, boxID)

	err = ctrl.storage.CreateExperimentProcess(experimentProcess)
	if err != nil {
		return errors.Trace(err)
	}

	err = ctrl.storage.UpdateBox(box)
	if err != nil {
		return errors.Trace(err)
	}
	return errors.Trace(ctrl.experimentCtl.StartExperiment(experimentProcess))
}

func parserRules(rules types.Rules, box *types.Box) types.Rules {
	var rs types.Rules
	for _, rule := range rules {
		rule.Type = types.JobType(strings.ToUpper(string(rule.Type)))
		if rule.Type == types.JobGitWebhook {
			rule.Value = fmt.Sprintf("tidb:%s:%s", box.Cat.TiDBConfig.Version.Type, box.Cat.TiDBConfig.Version.Value)
		}
		rs = append(rs, rule)
	}
	return rs
}
