package payments

import (
	"context"
	"testing"
	"time"

	"github.com/gofrs/uuid/v5"
	"github.com/saveinmed/backend-go/internal/domain"
)

func TestNewMercadoPagoGateway(t *testing.T) {
	gateway := NewMercadoPagoGateway("https://api.mercadopago.com", 2.5)

	if gateway.BaseURL != "https://api.mercadopago.com" {
		t.Errorf("expected BaseURL 'https://api.mercadopago.com', got '%s'", gateway.BaseURL)
	}
	if gateway.MarketplaceCommission != 2.5 {
		t.Errorf("expected commission 2.5, got %f", gateway.MarketplaceCommission)
	}
}

func TestCreatePreference(t *testing.T) {
	gateway := NewMercadoPagoGateway("https://api.mercadopago.com", 2.5)

	order := &domain.Order{
		ID:         uuid.Must(uuid.NewV4()),
		BuyerID:    uuid.Must(uuid.NewV4()),
		SellerID:   uuid.Must(uuid.NewV4()),
		TotalCents: 10000, // R$100
	}

	ctx := context.Background()
	pref, err := gateway.CreatePreference(ctx, order)
	if err != nil {
		t.Fatalf("failed to create preference: %v", err)
	}

	if pref.OrderID != order.ID {
		t.Errorf("expected order ID %s, got %s", order.ID, pref.OrderID)
	}
	if pref.Gateway != "mercadopago" {
		t.Errorf("expected gateway 'mercadopago', got '%s'", pref.Gateway)
	}
	if pref.CommissionPct != 2.5 {
		t.Errorf("expected commission 2.5, got %f", pref.CommissionPct)
	}

	// Test marketplace fee calculation (2.5% of 10000 = 250)
	expectedFee := int64(250)
	if pref.MarketplaceFee != expectedFee {
		t.Errorf("expected marketplace fee %d, got %d", expectedFee, pref.MarketplaceFee)
	}

	// Test seller receivable calculation (10000 - 250 = 9750)
	expectedReceivable := int64(9750)
	if pref.SellerReceivable != expectedReceivable {
		t.Errorf("expected seller receivable %d, got %d", expectedReceivable, pref.SellerReceivable)
	}

	// Test payment URL format
	expectedURL := "https://api.mercadopago.com/checkout/v1/redirect?order_id=" + order.ID.String()
	if pref.PaymentURL != expectedURL {
		t.Errorf("expected URL '%s', got '%s'", expectedURL, pref.PaymentURL)
	}
}

func TestCreatePreferenceWithDifferentCommissions(t *testing.T) {
	testCases := []struct {
		name           string
		commission     float64
		totalCents     int64
		expectedFee    int64
		expectedSeller int64
	}{
		{"5% commission", 5.0, 10000, 500, 9500},
		{"10% commission", 10.0, 10000, 1000, 9000},
		{"0% commission", 0.0, 10000, 0, 10000},
		{"2.5% on large order", 2.5, 100000, 2500, 97500},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			gateway := NewMercadoPagoGateway("https://test.com", tc.commission)
			order := &domain.Order{
				ID:         uuid.Must(uuid.NewV4()),
				TotalCents: tc.totalCents,
			}

			pref, err := gateway.CreatePreference(context.Background(), order)
			if err != nil {
				t.Fatalf("failed to create preference: %v", err)
			}

			if pref.MarketplaceFee != tc.expectedFee {
				t.Errorf("expected fee %d, got %d", tc.expectedFee, pref.MarketplaceFee)
			}
			if pref.SellerReceivable != tc.expectedSeller {
				t.Errorf("expected seller receivable %d, got %d", tc.expectedSeller, pref.SellerReceivable)
			}
		})
	}
}

func TestCreatePreferenceWithCancelledContext(t *testing.T) {
	gateway := NewMercadoPagoGateway("https://api.mercadopago.com", 2.5)

	order := &domain.Order{
		ID:         uuid.Must(uuid.NewV4()),
		TotalCents: 10000,
	}

	ctx, cancel := context.WithCancel(context.Background())
	cancel() // Cancel immediately

	_, err := gateway.CreatePreference(ctx, order)
	if err == nil {
		t.Error("expected error for cancelled context")
	}
}

func TestCreatePreferenceWithTimeout(t *testing.T) {
	gateway := NewMercadoPagoGateway("https://api.mercadopago.com", 2.5)

	order := &domain.Order{
		ID:         uuid.Must(uuid.NewV4()),
		TotalCents: 10000,
	}

	// Create a context that will timeout after a very short duration
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
	defer cancel()

	// Wait for context to expire
	time.Sleep(10 * time.Millisecond)

	_, err := gateway.CreatePreference(ctx, order)
	if err == nil {
		t.Error("expected error for timed out context")
	}
}

func TestCreatePreferenceWithZeroTotal(t *testing.T) {
	gateway := NewMercadoPagoGateway("https://api.mercadopago.com", 2.5)

	order := &domain.Order{
		ID:         uuid.Must(uuid.NewV4()),
		TotalCents: 0,
	}

	pref, err := gateway.CreatePreference(context.Background(), order)
	if err != nil {
		t.Fatalf("failed to create preference: %v", err)
	}

	if pref.MarketplaceFee != 0 {
		t.Errorf("expected fee 0, got %d", pref.MarketplaceFee)
	}
	if pref.SellerReceivable != 0 {
		t.Errorf("expected seller receivable 0, got %d", pref.SellerReceivable)
	}
}
