package xplan

import (
	"testing"

	"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/batchmeta"
	"github.com/tech/sendico/payments/storage/model"
	paymenttypes "github.com/tech/sendico/pkg/payments/types"
)

func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranches(t *testing.T) {
	compiler := New()

	targetsRaw, err := batchmeta.EncodePayoutTargets([]batchmeta.PayoutTarget{
		{
			TargetRef: "recipient-1",
			Comment:   "batch-comment-1",
			Amount:    &paymenttypes.Money{Amount: "100", Currency: "RUB"},
			Card:      &model.CardEndpoint{Pan: "2200700142860161", ExpMonth: 3, ExpYear: 2030},
		},
		{
			TargetRef: "recipient-2",
			Comment:   "batch-comment-2",
			Amount:    &paymenttypes.Money{Amount: "150", Currency: "RUB"},
			Card:      &model.CardEndpoint{Pan: "2200700142860162", ExpMonth: 4, ExpYear: 2030},
		},
	})
	if err != nil {
		t.Fatalf("EncodePayoutTargets returned error: %v", err)
	}

	intent := testIntent(model.PaymentKindPayout)
	intent.Attributes = map[string]string{
		batchmeta.AttrPayoutTargets: targetsRaw,
	}

	graph, err := compiler.Compile(Input{
		IntentSnapshot: intent,
		QuoteSnapshot: &model.PaymentQuoteSnapshot{
			Route: &paymenttypes.QuoteRouteSpecification{
				Hops: []*paymenttypes.QuoteRouteHop{
					{Index: 10, Rail: "LEDGER", Role: paymenttypes.QuoteRouteHopRoleSource},
					{Index: 20, Rail: "CARD", Gateway: "gw-card", Role: paymenttypes.QuoteRouteHopRoleDestination},
				},
			},
		},
	})
	if err != nil {
		t.Fatalf("Compile returned error: %v", err)
	}
	if graph == nil {
		t.Fatal("expected graph")
	}
	if got, want := len(graph.Steps), 11; got != want {
		t.Fatalf("steps count mismatch: got=%d want=%d", got, want)
	}
	if got, want := graph.Steps[0].StepCode, "edge.10_20.ledger.block"; got != want {
		t.Fatalf("first step mismatch: got=%q want=%q", got, want)
	}

	sendSteps := make([]Step, 0, 2)
	for i := range graph.Steps {
		step := graph.Steps[i]
		if step.StepCode != "hop.20.card_payout.send" {
			continue
		}
		sendSteps = append(sendSteps, step)
	}
	if got, want := len(sendSteps), 2; got != want {
		t.Fatalf("send steps mismatch: got=%d want=%d", got, want)
	}

	seenTargets := map[string]string{}
	seenComments := map[string]string{}
	for i := range sendSteps {
		step := sendSteps[i]
		if got, want := step.DependsOn, []string{graph.Steps[0].StepRef}; !equalStringSlice(got, want) {
			t.Fatalf("send step deps mismatch: got=%v want=%v", got, want)
		}
		targetRef := step.Metadata[batchmeta.MetaPayoutTargetRef]
		amount := step.Metadata[batchmeta.MetaAmount]
		comment := step.Comment
		if targetRef == "" || amount == "" || comment == "" {
			t.Fatalf("expected target fields on send step, metadata=%v comment=%q", step.Metadata, step.Comment)
		}
		seenTargets[targetRef] = amount
		seenComments[targetRef] = comment
	}
	if got, want := seenTargets["recipient-1"], "100"; got != want {
		t.Fatalf("recipient-1 amount mismatch: got=%q want=%q", got, want)
	}
	if got, want := seenTargets["recipient-2"], "150"; got != want {
		t.Fatalf("recipient-2 amount mismatch: got=%q want=%q", got, want)
	}
	if got, want := seenComments["recipient-1"], "batch-comment-1"; got != want {
		t.Fatalf("recipient-1 comment mismatch: got=%q want=%q", got, want)
	}
	if got, want := seenComments["recipient-2"], "batch-comment-2"; got != want {
		t.Fatalf("recipient-2 comment mismatch: got=%q want=%q", got, want)
	}
}
