package br

import (
	"context"

	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/entity"
	"github.com/tidbcloud/cluster-service-ng/pkg/clustergateway"
	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/executorext"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/repo"
)

// api input & output
type CreateLightweightRestoreInput struct {
	*apiv1.CreateLightweightRestoreRequest
}
type GetLightweightRestoreInput struct {
	*apiv1.GetLightweightRestoreRequest
}
type GetLightweightRestoreOutput struct {
	Status  apiv1.LightweightRestoreStatus
	Message string
	Failure *apiv1.RestoreFailure

	// kernel data restoring progress
	DataRestoreDurationSeconds    uint64
	DataRestoreBytes              uint64
	DataRestoreStep               string
	DataRestoreProgressPercentage uint32
}
type GetLightweightRestorePostActionsInput struct {
	*apiv1.GetLightweightRestorePostActionsRequest
}

type GetLightweightRestorePostActionsOutput struct {
	*apiv1.GetLightweightRestorePostActionsResponse
}
type DeleteLightweightRestoreInput struct {
	*apiv1.DeleteLightweightRestoreRequest
}

// common abstraction for lightweight restore
type LightweightRestoreAdaptor interface {
	// static meta
	GetCreationDagMeta(restoreId, targetSharedPoolId string) *LightweightRestoreDagMeta
	GetDeletionDagMeta(restoreId, targetSharedPoolId string) *LightweightRestoreDagMeta
	// runtime status
	GetRestoreInRunning(ctx context.Context, restore *entity.LightweightRestore) (*GetLightweightRestoreOutput, error)
	GetPostActions(ctx context.Context, restore *entity.LightweightRestore) (*GetLightweightRestorePostActionsOutput, error)
}

type LightweightRestoreDagMeta struct {
	DagName            string
	DagInstanceName    string
	DagInstanceFilters []executorext.DagInsFilter
}

type LightweightRestoreAdaptorIdentifier interface {
	GetSourceSharedPoolId() string
	GetTargetSharedPoolId() string
}

func kernelRestoreFailure(code, message string) *apiv1.RestoreFailure {
	return &apiv1.RestoreFailure{
		Source:  apiv1.RestoreFailureSource_KERNEL,
		Code:    code,
		Message: message,
	}
}

func GetLightweightRestoreAdaptor(
	identifier LightweightRestoreAdaptorIdentifier,
	clustergatewayCli clustergateway.Client,
	sharedPoolRepo repo.SharedPoolRepo,
) LightweightRestoreAdaptor {
	if identifier.GetSourceSharedPoolId() == identifier.GetTargetSharedPoolId() {
		return NewLwRestoreSameSharedPoolAdaptor(clustergatewayCli, sharedPoolRepo)
	}
	return NewLwRestoreCrossSharedPoolAdaptor(clustergatewayCli, sharedPoolRepo)
}
