package orchestrator

import (
	"context"

	"github.com/tech/sendico/payments/orchestrator/storage"
	"github.com/tech/sendico/payments/orchestrator/storage/model"
	"go.uber.org/zap"
)

func (p *paymentExecutor) releasePaymentHold(ctx context.Context, store storage.PaymentsStore, payment *model.Payment) error {
	if store == nil {
		return errStorageUnavailable
	}
	if payment == nil || payment.PaymentPlan == nil || len(payment.PaymentPlan.Steps) == 0 {
		return nil
	}
	execPlan := ensureExecutionPlanForPlan(payment, payment.PaymentPlan)
	if execPlan == nil || !blockStepConfirmed(payment.PaymentPlan, execPlan) {
		return nil
	}
	execSteps := executionStepsByCode(execPlan)
	execQuote := executionQuote(payment, nil)

	for idx, step := range payment.PaymentPlan.Steps {
		if step == nil || step.Action != model.RailOperationRelease {
			continue
		}
		stepID := planStepID(step, idx)
		execStep := execSteps[stepID]
		if execStep == nil {
			execStep = &model.ExecutionStep{Code: stepID}
			execSteps[stepID] = execStep
			if idx < len(execPlan.Steps) {
				execPlan.Steps[idx] = execStep
			}
		}
		status := executionStepStatus(execStep)
		if status == executionStepStatusConfirmed {
			p.logger.Debug("Payment step already confirmed, skipping", zap.String("step_id", stepID), zap.String("quutation", execQuote.QuoteRef))
			continue
		}
		if _, err := p.executePlanStep(ctx, payment, step, execStep, execQuote, nil, idx); err != nil {
			p.logger.Warn("Failed to execute payment step", zap.Error(err),
				zap.String("step_id", stepID), zap.String("quutation", execQuote.QuoteRef))
			return err
		}
	}

	return p.persistPayment(ctx, store, payment)
}
