package orchestrator

import (
	"context"
	"testing"

	paymodel "github.com/tech/sendico/payments/orchestrator/storage/model"
	mloggerfactory "github.com/tech/sendico/pkg/mlogger/factory"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/pkg/payments/rail"
)

func TestGatewayExecutionSuccessUpdatesMetadataOnly(t *testing.T) {
	logger := mloggerfactory.NewLogger(false)
	store := newHelperPaymentStore()

	payment := &paymodel.Payment{
		PaymentRef: "pi-1",
		State:      paymodel.PaymentStateSubmitted,
	}
	if err := store.Create(context.Background(), payment); err != nil {
		t.Fatalf("failed to seed payment: %v", err)
	}

	svc := &Service{
		logger:  logger,
		storage: stubRepo{payments: store},
	}

	exec := &model.PaymentGatewayExecution{
		PaymentRef:     "pi-1",
		Status:         rail.OperationResultSuccess,
		IdempotencyKey: "idem-1",
		OperationRef:   "oper-1",
	}

	if err := svc.onGatewayExecution(context.Background(), exec); err != nil {
		t.Fatalf("onGatewayExecution error: %v", err)
	}

	updated, _ := store.GetByPaymentRef(context.Background(), "pi-1")

	// Should not be Settled without execution plan
	if updated.State != paymodel.PaymentStateSubmitted {
		t.Fatalf("expected payment to remain submitted, got %s", updated.State)
	}

	if updated.Metadata["gateway_request_idempotency"] != "idem-1" {
		t.Fatalf("expected gateway_request_idempotency metadata")
	}

	if updated.Metadata["gateway_operation_result"] != string(rail.OperationResultSuccess) {
		t.Fatalf("expected gateway_operation_result metadata")
	}
}

func TestGatewayExecutionRejectedFailsPayment(t *testing.T) {
	logger := mloggerfactory.NewLogger(false)
	store := newHelperPaymentStore()

	payment := &paymodel.Payment{
		PaymentRef: "pi-2", State: paymodel.PaymentStateSubmitted, IdempotencyKey: "idem-1",
		ExecutionPlan: &paymodel.ExecutionPlan{
			Steps: []*paymodel.ExecutionStep{
				{OperationRef: "s1", State: paymodel.OperationStatePlanned, TransferRef: "trn-1"}}}}

	if err := store.Create(context.Background(), payment); err != nil {
		t.Fatalf("failed to seed payment: %v", err)
	}

	svc := &Service{
		logger:  logger,
		storage: stubRepo{payments: store},
	}

	exec := &model.PaymentGatewayExecution{
		PaymentRef:  "pi-2",
		TransferRef: "trn-1",
		Status:      rail.OperationResultFailed,
	}

	if err := svc.onGatewayExecution(context.Background(), exec); err != nil {
		t.Fatalf("onGatewayExecution error: %v", err)
	}

	updated, _ := store.GetByPaymentRef(context.Background(), "pi-2")

	if updated.State != paymodel.PaymentStateFailed {
		t.Fatalf("expected payment failed, got %s", updated.State)
	}

	if updated.FailureReason != "execution_plan_failed" {
		t.Fatalf("expected failure reason execution_plan_failed, got %q", updated.FailureReason)
	}
}
