package sales

import (
	"testing"

	"github.com/shopspring/decimal"
)

// The order carries its payment method ONLY as the notes marker checkout
// writes. The POS pickup screen guessed "is it cash?" and labelled every other
// order "Menunggu Transfer" — which told a cashier to expect a bank transfer
// for an unpaid QRIS order. These cases pin the parse that replaces the guess.
func TestPaymentMethodFromNotes(t *testing.T) {
	cases := []struct {
		name  string
		notes *string
		want  string
	}{
		{"nil notes", nil, ""},
		{"cash marker", strPtr("[Metode: cash]"), "cash"},
		{"cash marker with note text", strPtr("[Metode: cash] Tolong dibungkus"), "cash"},
		{"transfer marker", strPtr("[Metode: transfer]"), "transfer"},
		{"tempo marker", strPtr("[Metode: tempo]"), "tempo"},
		{"gateway marker", strPtr("[Metode: gateway]"), "gateway"},
		{"qris marker", strPtr("[Metode: qris]"), "qris"},
		{"duplicated marker (cart + checkout)", strPtr("[Metode: cash] [Metode: cash]"), "cash"},
		{"mixed case", strPtr("[METODE: Transfer]"), "transfer"},
		{"marker with spaces", strPtr("[Metode: bank transfer]"), "bank_transfer"},
		{"legacy cash without marker", strPtr("bayar tunai di kasir"), "cash"},
		{"unrelated notes", strPtr("kirim pagi"), ""},
		{"empty notes", strPtr(""), ""},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := paymentMethodFromNotes(tc.notes); got != tc.want {
				t.Fatalf("paymentMethodFromNotes(%v) = %q, want %q", tc.notes, got, tc.want)
			}
		})
	}
}

func TestIsUpfrontPaymentRequired(t *testing.T) {
	fiftyK := decimal.NewFromInt(50000)
	cases := []struct {
		name  string
		order *SalesOrder
		want  bool
	}{
		{"nil order", nil, false},
		{
			"regular order with cash method (COD)",
			&SalesOrder{
				OrderType:     "regular",
				PaymentMethod: "cash",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			false,
		},
		{
			"regular order with tempo method",
			&SalesOrder{
				OrderType:     "regular",
				PaymentMethod: "tempo",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			false,
		},
		{
			"regular order with payment terms > 0",
			&SalesOrder{
				OrderType:    "regular",
				PaymentTerms: 14,
				TotalAmount:  fiftyK,
				PaidAmount:   decimal.Zero,
			},
			false,
		},
		{
			"regular order with empty method and empty notes (legacy backoffice order)",
			&SalesOrder{
				OrderType:   "regular",
				TotalAmount: fiftyK,
				PaidAmount:  decimal.Zero,
			},
			false, // Not blocked as stranded transfer!
		},
		{
			"regular order with explicit transfer method unpaid",
			&SalesOrder{
				OrderType:     "regular",
				PaymentMethod: "transfer",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			true, // Upfront transfer required
		},
		{
			"regular order with explicit transfer method fully paid",
			&SalesOrder{
				OrderType:     "regular",
				PaymentMethod: "transfer",
				TotalAmount:   fiftyK,
				PaidAmount:    fiftyK,
			},
			false,
		},
		{
			"regular order with transfer in notes unpaid",
			&SalesOrder{
				OrderType:   "regular",
				Notes:       strPtr("Tolong transfer ke BCA"),
				TotalAmount: fiftyK,
				PaidAmount:  decimal.Zero,
			},
			true,
		},
		{
			"ecommerce order unpaid transfer",
			&SalesOrder{
				OrderType:     "ecommerce",
				PaymentMethod: "transfer",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			true,
		},
		{
			"ecommerce order cash / COD",
			&SalesOrder{
				OrderType:     "ecommerce",
				PaymentMethod: "cash",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			false,
		},
		{
			// The reported "stuck di Menunggu Pembayaran": an e-commerce order
			// with NO method recorded was treated as an unpaid transfer and
			// could never be packed. No method is not evidence of a transfer.
			"ecommerce order with no method recorded",
			&SalesOrder{
				OrderType:   "ecommerce",
				TotalAmount: fiftyK,
				PaidAmount:  decimal.Zero,
			},
			false,
		},
		{
			"ecommerce order qris unpaid",
			&SalesOrder{
				OrderType:     "ecommerce",
				PaymentMethod: "qris",
				TotalAmount:   fiftyK,
				PaidAmount:    decimal.Zero,
			},
			true,
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := isUpfrontPaymentRequired(tc.order); got != tc.want {
				t.Fatalf("isUpfrontPaymentRequired = %v, want %v", got, tc.want)
			}
		})
	}
}
