package br

import (
	"fmt"

	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/mysql/schema"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/repo"
	"github.com/tidbcloud/cluster-service-ng/pkg/utils"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

const MarkManualBackupSucceededActionName = "mark-manual-backup-succeeded"

type markManualBackupSucceededAction struct {
	manualBackupRepo repo.ManualBackupRepo
}

func NewMarkManualBackupSucceededAction(manualBackupRepo repo.ManualBackupRepo) actions.Action {
	return &markManualBackupSucceededAction{
		manualBackupRepo: manualBackupRepo,
	}
}

func (a *markManualBackupSucceededAction) Name() string {
	return MarkManualBackupSucceededActionName
}

func (a *markManualBackupSucceededAction) Invoke(args actions.ActionArgs) error {
	ctx := utils.GenerateContext(args)
	tilog.Info(ctx, fmt.Sprintf("start %s action...", a.Name()))

	backupID, existed := GetManualBackupID(args)
	if !existed {
		return fmt.Errorf("manual backup id is required, but not found in args: %v", args)
	}

	clusterID, existed := GetTiDBClusterID(args)
	if !existed {
		return fmt.Errorf("tidb cluster id is required, but not found in args: %v", args)
	}

	manualBackup, err := a.manualBackupRepo.Load(ctx, clusterID, backupID, false)
	if err != nil {
		tilog.Error(ctx, "failed to load manual backup", zap.Error(err), zap.String("backupId", backupID), zap.String("clusterId", clusterID))
		return fmt.Errorf("failed to load manual backup: %w", err)
	}
	if manualBackup.Status != schema.ManualBackupStatusRunning {
		tilog.Info(ctx, "skip mark manual backup succeeded because backup is not running",
			zap.String("backupId", backupID),
			zap.String("clusterId", clusterID),
			zap.String("status", manualBackup.Status))
		return nil
	}

	err = AddActionForManualBackup(ctx, a.manualBackupRepo, manualBackup, schema.ManualBackupActionMarkSucceeded)
	if err != nil {
		tilog.Error(ctx, "failed to add action to manual backup", zap.Error(err), zap.String("backupId", backupID), zap.String("clusterId", clusterID))
		return fmt.Errorf("failed to add action to manual backup: %w", err)
	}

	if err := a.manualBackupRepo.SetStatus(ctx, clusterID, backupID, schema.ManualBackupStatusSucceeded); err != nil {
		tilog.Error(ctx, "failed to mark manual backup succeeded", zap.Error(err), zap.String("backupId", backupID), zap.String("clusterId", clusterID))
		return fmt.Errorf("failed to mark manual backup succeeded: %w", err)
	}

	tilog.Info(ctx, "mark manual backup succeeded", zap.String("backupId", backupID), zap.String("clusterId", clusterID))
	return nil
}
