package configchange

import (
	"context"
	"fmt"

	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"sigs.k8s.io/controller-runtime/pkg/log"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

const (
	CCStepNameChangeCMOnlyMarkAllDone = "ChangeCMOnly/mark-all-done"
)

type changeCMOnlyApplier struct {
}

func newChangeCMOnlyApplier() *changeCMOnlyApplier {
	out := &changeCMOnlyApplier{}
	return out
}

func (r *changeCMOnlyApplier) InitSteps(ctx context.Context, cc *cloudv1.ConfigChange) {
	utilruntime.Must(cc.AddStep(ctx, cloudv1.CCStepUpdateCR2Cluster, cloudv1.CCStepStatusPending, ""))
	utilruntime.Must(cc.AddStep(ctx, cloudv1.CCStepUpdateConfig2CM, cloudv1.CCStepStatusPending, ""))
	utilruntime.Must(cc.AddStep(ctx, CCStepNameChangeCMOnlyMarkAllDone, cloudv1.CCStepStatusPending, ""))
}

func (r *changeCMOnlyApplier) RegisterStepAction(re *ConfigChangeReconciler) {
	re.RegisterAction(CCStepNameChangeCMOnlyMarkAllDone, r.Apply)
}

func (r *changeCMOnlyApplier) Apply(ctx context.Context, rx *ReconcileContext) (err error) {
	logger := log.FromContext(ctx)

	logger.Info("always mark Apply done")
	cc := rx.ConfigChange
	for _, compType := range cc.Status.ChangedComponents {
		comp := cc.ReadOnlyComponentStatus(compType)
		comp.Done = true
		comp.Reason = fmt.Sprintf("skipped, because the strategy is %s.", cc.Spec.ChangeStrategy)
		if err := cc.UpdateComponentStatus(ctx, compType, &comp); err != nil {
			return fmt.Errorf("update component status: %w", err)
		}
	}

	cc.UpdateStep(ctx, CCStepNameChangeCMOnlyMarkAllDone, cloudv1.CCStepStatusCompleted, "mark all components done")
	return nil
}
