package backend

import (
	"context"
	"time"

	"github.com/tidbcloud/chaos-svc/pkg/domain/facade"
	"github.com/tidbcloud/chaos-svc/pkg/domain/repo"
	cloudv1alpha1 "github.com/tidbcloud/eks-provider/api/v1alpha1"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/log"
	corev1 "k8s.io/api/core/v1"
)

type SyncBackendFromInfraSvc interface {
	Execute(ctx context.Context, projectID uint64, networkName string) bizerr.BizError
}

type syncBackendFromInfraImp struct {
	backendRepo repo.BackendRepo
	infraFacade facade.Infra
	timeFacade  facade.Time
}

func NewSyncBackendFromInfraSvc(
	backendRepo repo.BackendRepo,
	infraFacade facade.Infra,
	timeFacade facade.Time,
) SyncBackendFromInfraSvc {
	return &syncBackendFromInfraImp{
		backendRepo: backendRepo,
		infraFacade: infraFacade,
		timeFacade:  timeFacade,
	}
}

func (s *syncBackendFromInfraImp) Execute(ctx context.Context, projectID uint64, networkName string) bizerr.BizError {
	logger := log.WithContextL(ctx).Sugar().With("projectID", projectID, "networkName", networkName)

	backend, err := s.backendRepo.Load(ctx, projectID, networkName)
	if err != nil {
		return err
	}

	var statusErr bizerr.BizError
	cs, err := s.infraFacade.GetChaosServer(ctx, projectID, networkName)
	if err != nil {
		if err.ErrCode() == bizerr.ErrCodeRecordNotFound {
			logger.Infof("chaos backend not found, mark as disable finshed")
			statusErr = backend.FinishDisableForce(time.Now())
		} else {
			return err.Chain("get chaos backend from infra")
		}
	} else {
		readyCondition := cs.Status.Conditions.GetCondition(cloudv1alpha1.ConditionReady)
		switch readyCondition.Status {
		case corev1.ConditionTrue:
			logger.Infof("chaos backend ready condition is true, mark as enable successfully")
			statusErr = backend.EnableSucceed(readyCondition.LastTransitionTime.Time)
		case corev1.ConditionFalse:
			logger.Infof("chaos backend ready condition is false, mark as enable failed")
			statusErr = backend.EnableFailed(readyCondition.Reason, time.Now())
		case corev1.ConditionUnknown:
			logger.Infof("chaos backend ready condition is unknown, skip")
			fallthrough
		default:
		}
	}

	if statusErr != nil {
		return statusErr
	}

	return s.backendRepo.Save(ctx, backend)
}
