package prmap

import (
	"strings"

	"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg"
	"github.com/tech/sendico/pkg/merrors"
)

func validateMapInput(in MapInput) error {
	if in.Payment == nil {
		return merrors.InvalidArgument("payment is required")
	}
	return validatePaymentInvariants(in.Payment)
}

func validatePaymentInvariants(payment *agg.Payment) error {
	if payment == nil {
		return merrors.InvalidArgument("payment is required")
	}
	if strings.TrimSpace(payment.PaymentRef) == "" {
		return merrors.InvalidArgument("payment.payment_ref is required")
	}
	if strings.TrimSpace(payment.QuotationRef) == "" {
		return merrors.InvalidArgument("payment.quotation_ref is required")
	}
	if payment.IntentSnapshot.Amount == nil {
		return merrors.InvalidArgument("payment.intent_snapshot.amount is required")
	}
	if strings.TrimSpace(payment.IntentSnapshot.SettlementCurrency) == "" {
		return merrors.InvalidArgument("payment.intent_snapshot.settlement_currency is required")
	}
	if payment.QuoteSnapshot == nil {
		return merrors.InvalidArgument("payment.quote_snapshot is required")
	}
	if payment.QuoteSnapshot.DebitAmount == nil {
		return merrors.InvalidArgument("payment.quote_snapshot.debit_amount is required")
	}
	if _, ok := normalizeAggregateState(payment.State); !ok {
		return merrors.InvalidArgument("payment.state is invalid")
	}
	if payment.Version == 0 {
		return merrors.InvalidArgument("payment.version is required")
	}
	if payment.CreatedAt.IsZero() {
		return merrors.InvalidArgument("payment.created_at is required")
	}
	if payment.UpdatedAt.IsZero() {
		return merrors.InvalidArgument("payment.updated_at is required")
	}

	for i := range payment.StepExecutions {
		if err := validateStepInvariants(payment.StepExecutions[i], i); err != nil {
			return err
		}
	}
	return nil
}

func validateStepInvariants(step agg.StepExecution, index int) error {
	if strings.TrimSpace(step.StepRef) == "" {
		return merrors.InvalidArgument("payment.stepExecutions[" + itoa(index) + "].step_ref is required")
	}
	if _, ok := normalizeStepState(step.State); !ok {
		return merrors.InvalidArgument("payment.stepExecutions[" + itoa(index) + "].state is invalid")
	}
	return nil
}
