package orchestrator

import (
	"testing"

	fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
	moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
	chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
	oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
	orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
)

func TestResolveTradeAmountsBuyBase(t *testing.T) {
	fxQuote := &oraclev1.Quote{
		Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
		Pair: &fxv1.CurrencyPair{Base: "EUR", Quote: "USD"},
		BaseAmount: &moneyv1.Money{
			Currency: "EUR",
			Amount:   "100",
		},
		QuoteAmount: &moneyv1.Money{
			Currency: "USD",
			Amount:   "110",
		},
	}

	pay, settle := resolveTradeAmounts(nil, fxQuote, fxv1.Side_SIDE_UNSPECIFIED)
	if pay.GetCurrency() != "USD" || pay.GetAmount() != "110" {
		t.Fatalf("expected pay amount in USD 110, got %s %s", pay.GetCurrency(), pay.GetAmount())
	}
	if settle.GetCurrency() != "EUR" || settle.GetAmount() != "100" {
		t.Fatalf("expected settlement in EUR 100, got %s %s", settle.GetCurrency(), settle.GetAmount())
	}
}

func TestComputeAggregatesConvertsCurrencies(t *testing.T) {
	pay := &moneyv1.Money{Currency: "USD", Amount: "100"}
	settle := &moneyv1.Money{Currency: "EUR", Amount: "50"}
	fee := &moneyv1.Money{Currency: "USD", Amount: "10"}
	network := &chainv1.EstimateTransferFeeResponse{
		NetworkFee: &moneyv1.Money{Currency: "USD", Amount: "5"},
	}
	fxQuote := &oraclev1.Quote{
		Pair: &fxv1.CurrencyPair{Base: "EUR", Quote: "USD"},
		Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
		Price: &moneyv1.Decimal{
			Value: "2",
		},
	}

	debit, settlement := computeAggregates(pay, settle, fee, network, fxQuote, orchestratorv1.SettlementMode_SETTLEMENT_FIX_RECEIVED)
	if debit.GetCurrency() != "USD" || debit.GetAmount() != "115" {
		t.Fatalf("expected debit 115 USD, got %s %s", debit.GetCurrency(), debit.GetAmount())
	}
	if settlement.GetCurrency() != "EUR" || settlement.GetAmount() != "50" {
		t.Fatalf("expected settlement 50 EUR, got %s %s", settlement.GetCurrency(), settlement.GetAmount())
	}
}

func TestComputeAggregatesRecipientPaysFee(t *testing.T) {
	pay := &moneyv1.Money{Currency: "USDT", Amount: "100"}
	settle := &moneyv1.Money{Currency: "RUB", Amount: "7932"} // 100 * 79.32
	fee := &moneyv1.Money{Currency: "USDT", Amount: "7"}      // 7% of 100
	fxQuote := &oraclev1.Quote{
		Pair: &fxv1.CurrencyPair{Base: "USDT", Quote: "RUB"},
		Side: fxv1.Side_SELL_BASE_BUY_QUOTE,
		Price: &moneyv1.Decimal{
			Value: "79.32",
		},
	}

	debit, settlement := computeAggregates(pay, settle, fee, nil, fxQuote, orchestratorv1.SettlementMode_SETTLEMENT_FIX_SOURCE)
	if debit.GetCurrency() != "USDT" || debit.GetAmount() != "100" {
		t.Fatalf("expected debit 100 USDT, got %s %s", debit.GetCurrency(), debit.GetAmount())
	}
	if settlement.GetCurrency() != "RUB" || settlement.GetAmount() != "7376.76" {
		t.Fatalf("expected settlement 7376.76 RUB, got %s %s", settlement.GetCurrency(), settlement.GetAmount())
	}
}
