package workflow

import (
	"context"

	"github.com/tidbcloud/chaos-svc/idl/pbgen/proto/chaos"
	"github.com/tidbcloud/chaos-svc/pkg/domain/entity"
	"github.com/tidbcloud/chaos-svc/pkg/domain/facade"
	"github.com/tidbcloud/chaos-svc/pkg/domain/repo"
	"github.com/tidbcloud/pkgv2/bizerr"
)

type UpdateWorkflowSvc interface {
	Execute(ctx context.Context, params *UpdateWorkflowParam) (*entity.Workflow, bizerr.BizError)
}

type UpdateWorkflowParam struct {
	TiDBCluster facade.TiDBCluster
	WorkflowID  uint64
	Draft       *bool
	Summary     *string
	ReportLink  *string
}

type updateWorkflowImp struct {
	workflowRepo repo.WorkflowRepo
	infraFacade  facade.Infra
	timeFacade   facade.Time
}

func NewUpdateWorkflowSvc(
	workflowRepo repo.WorkflowRepo,
	infraFacade facade.Infra,
	timeFacade facade.Time,
) UpdateWorkflowSvc {
	return &updateWorkflowImp{
		workflowRepo: workflowRepo,
		infraFacade:  infraFacade,
		timeFacade:   timeFacade,
	}
}

func (imp *updateWorkflowImp) Execute(ctx context.Context, params *UpdateWorkflowParam) (*entity.Workflow, bizerr.BizError) {
	workflowEntity, err := imp.workflowRepo.Load(ctx, params.WorkflowID)
	if err != nil {
		return nil, err
	}
	if workflowEntity.ClusterID != params.TiDBCluster.ClusterID {
		return nil, bizerr.New(bizerr.ErrCodeRecordNotFound, "workflow not found in this cluster")
	}

	if params.ReportLink != nil {
		workflowEntity.SetReportLink(*params.ReportLink)
	}
	if params.Summary != nil {
		workflowEntity.SetSummary(*params.Summary)
	}
	if params.Draft != nil && !(*params.Draft) &&
		workflowEntity.Status == chaos.ExperimentStatus_EXPERIMENT_STATUS_DRAFT {
		workflowEntity.SetStatusRunning(imp.timeFacade.Now())
		if err := imp.infraFacade.CreateWorkflowIgnoreExist(ctx, workflowEntity); err != nil {
			return nil, err
		}
	}

	if err := imp.workflowRepo.Save(ctx, workflowEntity); err != nil {
		return nil, err
	}
	return workflowEntity, nil
}
