package settlement

import (
	"encoding/json"
	"testing"
)

func TestSettlementReferenceIsStableAndCompact(t *testing.T) {
	got := settlementReference("12345678-90ab-cdef-1234-567890abcdef", 2)
	want := "LOCAL-SEPA-1234567890ABCDEF-02"
	if got != want {
		t.Fatalf("settlementReference() = %q, want %q", got, want)
	}
}

func TestLocalProviderDecisionDefaultsToSuccess(t *testing.T) {
	decision := localProviderDecision(dueTransfer{PaymentReference: "Invoice 1001"}, 1)
	if decision.Outcome != providerSucceeded {
		t.Fatalf("Outcome = %q, want %q", decision.Outcome, providerSucceeded)
	}
}

func TestLocalProviderDecisionCanFailPermanently(t *testing.T) {
	decision := localProviderDecision(dueTransfer{PaymentReference: "SEPA_FAIL"}, 1)
	if decision.Outcome != providerPermanentFailure {
		t.Fatalf("Outcome = %q, want %q", decision.Outcome, providerPermanentFailure)
	}
}

func TestLocalProviderDecisionRetriesOnceThenSucceeds(t *testing.T) {
	transfer := dueTransfer{Description: "SEPA_RETRY"}
	first := localProviderDecision(transfer, 1)
	if first.Outcome != providerTemporaryFailure {
		t.Fatalf("first Outcome = %q, want %q", first.Outcome, providerTemporaryFailure)
	}

	second := localProviderDecision(transfer, 2)
	if second.Outcome != providerSucceeded {
		t.Fatalf("second Outcome = %q, want %q", second.Outcome, providerSucceeded)
	}
}

func TestLocalProviderDecisionCanKeepRetryingUntilMaxAttempts(t *testing.T) {
	for attempt := 1; attempt <= 3; attempt++ {
		decision := localProviderDecision(dueTransfer{PaymentReference: "SEPA_RETRY_FAIL"}, attempt)
		if decision.Outcome != providerTemporaryFailure {
			t.Fatalf("attempt %d Outcome = %q, want %q", attempt, decision.Outcome, providerTemporaryFailure)
		}
	}
}

func TestNormalizeProviderStatus(t *testing.T) {
	tests := map[string]string{
		"accepted":   "completed",
		"SETTLED":    "completed",
		"returned":   "failed",
		"processing": "pending",
		"custom":     "custom",
	}
	for input, want := range tests {
		if got := normalizeProviderStatus(input); got != want {
			t.Fatalf("normalizeProviderStatus(%q) = %q, want %q", input, got, want)
		}
	}
}

func TestJSONOrEmpty(t *testing.T) {
	if got := string(jsonOrEmpty(nil)); got != `{}` {
		t.Fatalf("nil JSON = %s, want {}", got)
	}
	valid := json.RawMessage(`{"ok":true}`)
	if got := string(jsonOrEmpty(valid)); got != string(valid) {
		t.Fatalf("valid JSON = %s, want %s", got, valid)
	}
	if got := string(jsonOrEmpty(json.RawMessage(`not-json`))); got != `{}` {
		t.Fatalf("invalid JSON = %s, want {}", got)
	}
}
