package admin

import (
	"errors"
	"math"
	"testing"

	"github.com/niels/banking-app/backend/internal/domain"
)

func TestNormalizeWalletAdjustment(t *testing.T) {
	t.Parallel()

	params, err := NormalizeWalletAdjustment(" ADD ", "eur", "Customer compensation", "request-1", 100)
	if err != nil {
		t.Fatalf("valid adjustment rejected: %v", err)
	}
	if params.Direction != "add" || params.Currency != "EUR" || params.Reason != "Customer compensation" {
		t.Fatalf("unexpected normalized adjustment: %+v", params)
	}

	if _, err := NormalizeWalletAdjustment("subtract", "EUR", "short", "request-2", 100); err == nil {
		t.Fatal("expected short reason to fail")
	}
	if _, err := NormalizeWalletAdjustment("invalid", "EUR", "Valid reason text", "request-3", 100); err == nil {
		t.Fatal("expected invalid direction to fail")
	}
	if _, err := NormalizeWalletAdjustment("add", "EUR", "Valid reason text", "", 100); err == nil {
		t.Fatal("expected missing idempotency key to fail")
	}
}

func TestSelectAdjustmentAccount(t *testing.T) {
	t.Parallel()

	accounts := []adjustmentAccount{
		{ID: "account-1", Status: "active"},
		{ID: "account-2", Status: "frozen"},
	}
	selected, err := selectAdjustmentAccount(accounts, "")
	if err != nil {
		t.Fatalf("single active account rejected: %v", err)
	}
	if selected.ID != "account-1" {
		t.Fatalf("unexpected account selected: %s", selected.ID)
	}

	accounts = append(accounts, adjustmentAccount{ID: "account-3", Status: "active"})
	if _, err := selectAdjustmentAccount(accounts, ""); err == nil {
		t.Fatal("expected multiple active accounts to require account_id")
	}
}

func TestCalculateAdjustedBalances(t *testing.T) {
	t.Parallel()

	wallet, account, err := calculateAdjustedBalances(1000, 800, "add", 200)
	if err != nil || wallet != 1200 || account != 1000 {
		t.Fatalf("unexpected add result: wallet=%d account=%d err=%v", wallet, account, err)
	}

	wallet, account, err = calculateAdjustedBalances(1000, 800, "subtract", 300)
	if err != nil || wallet != 700 || account != 500 {
		t.Fatalf("unexpected subtract result: wallet=%d account=%d err=%v", wallet, account, err)
	}

	if _, _, err := calculateAdjustedBalances(1000, 100, "subtract", 200); !errors.Is(err, domain.ErrInsufficientFunds) {
		t.Fatalf("expected insufficient funds, got %v", err)
	}
	if _, _, err := calculateAdjustedBalances(math.MaxInt64, 100, "add", 1); !errors.Is(err, domain.ErrValidation) {
		t.Fatalf("expected overflow validation error, got %v", err)
	}
}
