package base

import (
	"context"
	"fmt"

	"github.com/tidbcloud/dataflow-service/app/internal/feature_gate"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	restoreRepo "github.com/tidbcloud/dataflow-service/app/repo/restore"
	"github.com/tidbcloud/dataflow-service/app/utils"
	"github.com/tidbcloud/dataflow-service/pkg/grpc/grpcli"
	"github.com/tidbcloud/pkgv2/db"
	mgmt "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"go.uber.org/zap"
)

type BaseAction struct {
	TransProvider db.TransProvider
	CoreCli       grpcli.CoreGrpcClient
	MgmtSvcCli    grpcli.MgmtSvcGrpcClient
	RestoreRepo   restoreRepo.RestoreRepo
	FeatureGate   feature_gate.FeatureGate
}

func NewBaseAction(
	transProvider db.TransProvider,
	coreCli grpcli.CoreGrpcClient,
	mgmtSvcCli grpcli.MgmtSvcGrpcClient,
	restoreRepo restoreRepo.RestoreRepo,
	featuregate feature_gate.FeatureGate,
) BaseAction {
	return BaseAction{
		TransProvider: transProvider,
		CoreCli:       coreCli,
		MgmtSvcCli:    mgmtSvcCli,
		RestoreRepo:   restoreRepo,
		FeatureGate:   featuregate,
	}
}

func (a *BaseAction) GenerateRestoreCRName(restore *entity.Restore) string {
	if restore.ExtraInfo != nil && restore.ExtraInfo.RestoreCRNameVersion == "v1" {
		return utils.UniqueIdentifierLte63(fmt.Sprintf("restore-%d", restore.ID))
	}
	return utils.UniqueIdentifierLte63(fmt.Sprintf("cluster-%d-restore-%d", restore.ClusterID, restore.ID))
}

func (a *BaseAction) GetCluster(ctx context.Context, logger *zap.Logger, clusterID uint64) (*mgmt.Cluster, error) {
	cluster, err := a.MgmtSvcCli.GetAnyDedicatedClusterBasicByID(ctx, clusterID)
	if err != nil {
		logger.Error("get cluster error", zap.Uint64("cluster id", clusterID), zap.Error(err))
		return nil, err
	}
	return cluster, nil
}

// EnhanceLoggerWithRestoreContext adds restore-related context information to the logger
// This helps with troubleshooting by including cluster_id, project_id, tenant_id in all log entries
func (a *BaseAction) EnhanceLoggerWithRestoreContext(logger *zap.Logger, restore *entity.Restore) *zap.Logger {
	return logger.With(
		zap.Uint64("restore_id", restore.ID.Uint64()),
		zap.Uint64("cluster_id", restore.ClusterID.Uint64()),
		zap.Uint64("project_id", restore.ProjectID.Uint64()),
		zap.Uint64("tenant_id", restore.TenantID.Uint64()),
		zap.Uint64("backup_id", restore.BackupID.Uint64()),
	)
}

// EnhanceLoggerWithContextIDs adds basic context IDs when only IDs are available
func (a *BaseAction) EnhanceLoggerWithContextIDs(
	logger *zap.Logger, restoreID, clusterID, projectID, tenantID, backupID uint64,
) *zap.Logger {
	return logger.With(
		zap.Uint64("restore_id", restoreID),
		zap.Uint64("cluster_id", clusterID),
		zap.Uint64("project_id", projectID),
		zap.Uint64("tenant_id", tenantID),
		zap.Uint64("backup_id", backupID),
	)
}
