package yookassa

import (
	"testing"
)

func TestParseNotification(t *testing.T) {
	n, err := ParseNotification([]byte(`{"type":"notification","event":"payment.succeeded",
		"object":{"id":"pay-1","status":"succeeded","paid":true,"metadata":{"order_id":"0197-order"}}}`))
	if err != nil {
		t.Fatalf("parse notification: %v", err)
	}
	if n.Event != EventPaymentSucceeded {
		t.Errorf("event = %q, want %q", n.Event, EventPaymentSucceeded)
	}
	p, err := n.Payment()
	if err != nil {
		t.Fatalf("decode notification payment: %v", err)
	}
	if p.ID != "pay-1" {
		t.Errorf("payment id = %q, want pay-1", p.ID)
	}
	if p.OrderID() != "0197-order" {
		t.Errorf("order id = %q, want the order carried in metadata", p.OrderID())
	}
}

func TestParseNotificationRejectsNonEnvelopes(t *testing.T) {
	for name, body := range map[string]string{
		"not json":     `nonsense`,
		"wrong type":   `{"type":"payment","event":"payment.succeeded","object":{"id":"pay-1"}}`,
		"no event":     `{"type":"notification","object":{"id":"pay-1"}}`,
		"empty object": `{}`,
	} {
		if _, err := ParseNotification([]byte(body)); err == nil {
			t.Errorf("%s: accepted as a notification envelope", name)
		}
	}
}

func TestNotificationPaymentNeedsAnID(t *testing.T) {
	// Without an id there is nothing to re-read from the API, and the body itself is never evidence.
	n, err := ParseNotification([]byte(`{"type":"notification","event":"payment.succeeded","object":{"status":"succeeded"}}`))
	if err != nil {
		t.Fatalf("parse notification: %v", err)
	}
	if _, err := n.Payment(); err == nil {
		t.Error("a payment object with no id was accepted")
	}
}

func TestParseRefundNotification(t *testing.T) {
	n, err := ParseNotification([]byte(`{"type":"notification","event":"refund.succeeded",
		"object":{"id":"refund-1","status":"succeeded","payment_id":"pay-1",
		"amount":{"value":"149.00","currency":"RUB"}}}`))
	if err != nil {
		t.Fatalf("parse notification: %v", err)
	}
	if n.Event != EventRefundSucceeded {
		t.Errorf("event = %q, want %q", n.Event, EventRefundSucceeded)
	}
	r, err := n.Refund()
	if err != nil {
		t.Fatalf("decode notification refund: %v", err)
	}
	// The refund names the payment, not our order — that is how it is resolved back to one.
	if r.ID != "refund-1" || r.PaymentID != "pay-1" {
		t.Errorf("refund = %+v, want refund-1 for pay-1", r)
	}
}

func TestNotificationRefundNeedsAnID(t *testing.T) {
	n, err := ParseNotification([]byte(`{"type":"notification","event":"refund.succeeded","object":{"status":"succeeded"}}`))
	if err != nil {
		t.Fatalf("parse notification: %v", err)
	}
	if _, err := n.Refund(); err == nil {
		t.Error("a refund object with no id was accepted")
	}
}
