package experiment

import (
	"context"

	"github.com/tidbcloud/chaos-svc/idl/pbgen/proto/chaos"
	"github.com/tidbcloud/chaos-svc/pkg/domain/facade"
	"github.com/tidbcloud/chaos-svc/pkg/domain/repo"
	workflowSvc "github.com/tidbcloud/chaos-svc/pkg/domain/service/workflow"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/db"
	"github.com/tidbcloud/pkgv2/log"
)

type DeleteExperimentSvc struct {
	trans             db.TransProvider
	infraFacade       facade.Infra
	deleteWorkflowSvc workflowSvc.DeleteWorkflowSvc
	specConverter     workflowSvc.SpecConverter
	workflowLockRepo  repo.WorkflowLockRepo
	workflowRepo      repo.WorkflowRepo
	backendRepo       repo.BackendRepo
}

func NewDeleteExperimentSvc(
	trans db.TransProvider,
	infraFacade facade.Infra,
	deleteWorkflowSvc workflowSvc.DeleteWorkflowSvc,
	specConverter workflowSvc.SpecConverter,
	workflowLockRepo repo.WorkflowLockRepo,
	workflowRepo repo.WorkflowRepo,
	backendRepo repo.BackendRepo,
) *DeleteExperimentSvc {
	return &DeleteExperimentSvc{
		trans:             trans,
		infraFacade:       infraFacade,
		deleteWorkflowSvc: deleteWorkflowSvc,
		specConverter:     specConverter,
		workflowLockRepo:  workflowLockRepo,
		workflowRepo:      workflowRepo,
		backendRepo:       backendRepo,
	}
}

func (svc *DeleteExperimentSvc) Execute(ctx context.Context, req *chaos.DeleteExperimentRequest) bizerr.BizError {
	logger := log.WithContextS(ctx).With("clusterID", req.ClusterId).With("projectID", req.ProjectId)
	logger.Info("delete experiment")

	tidbCluster, err := svc.infraFacade.GetTiDBCluster(ctx, req.ProjectId, req.ClusterId)
	if err != nil {
		return err
	}
	backend, err := svc.backendRepo.Load(ctx, tidbCluster.ProjectID, tidbCluster.NetworkName)
	if err != nil {
		return err
	}
	if err := ValidateChaosBackendReady(backend); err != nil {
		return err
	}

	if err := svc.trans.Transaction(ctx, func(ctx context.Context) error {
		params, err := svc.buildDeleteWorkflowParams(req, *tidbCluster)
		if err != nil {
			return err
		}

		if err := svc.deleteWorkflowSvc.Execute(ctx, params); err != nil {
			return err
		}
		return nil
	}); err != nil {
		return bizerr.WrapError(err, "transaction")
	}
	return nil
}

func (svc *DeleteExperimentSvc) buildDeleteWorkflowParams(req *chaos.DeleteExperimentRequest, tidbCluster facade.TiDBCluster) (*workflowSvc.DeleteWorkflowParam, bizerr.BizError) {
	return &workflowSvc.DeleteWorkflowParam{
		TiDBCluster: tidbCluster,
		WorkflowID:  req.ExperimentId,
	}, nil
}
