package gateway

import (
	"strings"
)

const (
	providerCodeDeclineAmountOrFrequencyLimit = "10101"
)

type payoutFailureAction int

const (
	payoutFailureActionFail payoutFailureAction = iota + 1
	payoutFailureActionRetry
)

type payoutFailureDecision struct {
	Action payoutFailureAction
	Reason string
}

type payoutFailurePolicy struct {
	providerCodeActions map[string]payoutFailureAction
}

func defaultPayoutFailurePolicy() payoutFailurePolicy {
	return payoutFailurePolicy{
		providerCodeActions: map[string]payoutFailureAction{
			providerCodeDeclineAmountOrFrequencyLimit: payoutFailureActionRetry,
		},
	}
}

func (p payoutFailurePolicy) decideProviderFailure(code string) payoutFailureDecision {
	normalized := strings.TrimSpace(code)
	if normalized == "" {
		return payoutFailureDecision{
			Action: payoutFailureActionFail,
			Reason: "provider_failure",
		}
	}
	if action, ok := p.providerCodeActions[normalized]; ok {
		return payoutFailureDecision{
			Action: action,
			Reason: "provider_code_" + normalized,
		}
	}
	return payoutFailureDecision{
		Action: payoutFailureActionFail,
		Reason: "provider_code_" + normalized,
	}
}

func (p payoutFailurePolicy) decideTransportFailure() payoutFailureDecision {
	return payoutFailureDecision{
		Action: payoutFailureActionRetry,
		Reason: "transport_failure",
	}
}

func payoutFailureReason(code, message string) string {
	cleanCode := strings.TrimSpace(code)
	cleanMessage := strings.TrimSpace(message)
	switch {
	case cleanCode != "" && cleanMessage != "":
		return cleanCode + ": " + cleanMessage
	case cleanCode != "":
		return cleanCode
	default:
		return cleanMessage
	}
}

func retryDelayForAttempt(attempt uint32) int {
	// Backoff in seconds by attempt number (attempt starts at 1).
	switch {
	case attempt <= 1:
		return 5
	case attempt == 2:
		return 15
	case attempt == 3:
		return 30
	default:
		return 60
	}
}
