package galon

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/shopspring/decimal"
)

// One completed galon handover = one posted journal entry. A deposit is a
// LIABILITY line (Uang Muka / Deposit Customer), a sale is a REVENUE line
// (Pendapatan Depot Galon Air) — and before this hook existed, galon money
// was visible in payments but invisible in the buku besar.
func TestJournalFiresOnCompletion(t *testing.T) {
	fs := newFakeStore()
	var calls []GalonJournalInput
	svc := NewService(fs, &fakeSeq{}, time.UTC).
		WithPayments(&fakePayments{}).
		WithJournal(func(_ context.Context, in GalonJournalInput) (string, error) {
			calls = append(calls, in)
			return "JRN-1", nil
		})

	ctx := context.Background()
	if _, err := svc.Create(ctx, TransactionInput{
		CustomerID: 1, Type: "refill", FulfillmentMode: "pickup",
		Quantity: decimal.NewFromInt(1), UnitPrice: decimal.NewFromInt(6000),
		DepositAmount: decimal.NewFromInt(20000),
	}); err != nil {
		t.Fatalf("create: %v", err)
	}
	if _, err := svc.Complete(ctx, 1); err != nil {
		t.Fatalf("complete: %v", err)
	}

	if len(calls) != 1 {
		t.Fatalf("journal calls = %d, want 1", len(calls))
	}
	in := calls[0]
	if in.Revenue != 6000 {
		t.Errorf("revenue = %v, want 6000", in.Revenue)
	}
	if in.DepositAmount != 20000 {
		t.Errorf("deposit = %v, want 20000", in.DepositAmount)
	}
	if in.TransactionNumber == "" {
		t.Error("transaction number missing from journal input")
	}
}

// A journal failure must NOT be swallowed — a missing ledger entry is exactly
// the silence that hid galon from the books. The completion stays committed
// (the money DID move), but the handler surfaces the error.
func TestJournalFailureSurfaces(t *testing.T) {
	fs := newFakeStore()
	svc := NewService(fs, &fakeSeq{}, time.UTC).
		WithPayments(&fakePayments{}).
		WithJournal(func(_ context.Context, _ GalonJournalInput) (string, error) {
			return "", errors.New("journal down")
		})

	ctx := context.Background()
	if _, err := svc.Create(ctx, TransactionInput{
		CustomerID: 1, Type: "refill", FulfillmentMode: "pickup",
		Quantity: decimal.NewFromInt(1), UnitPrice: decimal.NewFromInt(6000),
	}); err != nil {
		t.Fatalf("create: %v", err)
	}
	_, err := svc.Complete(ctx, 1)
	if err == nil {
		t.Fatal("journal failure was swallowed")
	}
	if err.Error() != "journal down" {
		t.Fatalf("unexpected error: %v", err)
	}
}
