package sales

import (
	"context"
	"testing"

	"github.com/TaruLab/keluargamart-backend/internal/auth"

	"github.com/shopspring/decimal"
)

// Reproduksi laporan kasir: tombol "Serahkan Barang" di POS Ambil Toko.
// Order pickup cash baru = pending_approval; kasir men PATCH delivered.
func TestHandoverPendingApprovalCashPickup(t *testing.T) {
	s := svc()
	fs := s.store.(*fakeStore)
	fs.stocks["1:1"] = &Stock{ID: 1, ProductID: 1, WarehouseID: 1, Quantity: decimal.NewFromInt(10)}

	addr := "[Ambil Sendiri di Toko] Gudang Pusat Medan · Pengambil: QA (0812)"
	notes := "[Metode: cash]"
	o, err := s.PlaceCheckout(context.Background(), CheckoutInput{
		Items:           []CheckoutItemInput{{ProductID: 1, Quantity: decimal.NewFromInt(1)}},
		PaymentMethod:   "cash",
		Notes:           &notes,
		ShippingAddress: &addr,
		WarehouseID:     1,
	}, 42, "Buyer", "buyer@keluargamart.local")
	if err != nil {
		t.Fatalf("checkout: %v", err)
	}
	if o.Status != "pending_approval" {
		t.Fatalf("precondition: status = %s", o.Status)
	}

	// Kasir (role cashier) menyerahkan barang.
	cashierCtx := auth.ToContext(context.Background(), &auth.User{ID: 7, Role: auth.RoleCashier}, 1)
	got, err := s.AdvanceFulfillment(cashierCtx, o.ID, "delivered")
	if err != nil {
		t.Logf("HANDOVER FAILED: %v", err)
		t.Fail()
		return
	}
	if got.Status != "delivered" {
		t.Fatalf("status = %s, want delivered", got.Status)
	}
	if !got.PaidAmount.Equal(got.TotalAmount) {
		t.Errorf("cash order harus auto-settle saat serah terima: paid=%s total=%s", got.PaidAmount, got.TotalAmount)
	}
}

// Approving a pickup in ERP runs onConfirm, which issues the invoice and moves
// the order to 'invoiced'. The till must still be able to hand that order over
// — this is the reported "invalid order status" when confirming in Ambil Toko.
func TestHandoverFromInvoicedCashPickup(t *testing.T) {
	s := svc()
	fs := s.store.(*fakeStore)
	fs.stocks["1:1"] = &Stock{ID: 1, ProductID: 1, WarehouseID: 1, Quantity: decimal.NewFromInt(10)}

	addr := "[Ambil Sendiri di Toko] Gudang Pusat Medan · Pengambil: QA (0812)"
	notes := "[Metode: cash]"
	o, err := s.PlaceCheckout(context.Background(), CheckoutInput{
		Items:           []CheckoutItemInput{{ProductID: 1, Quantity: decimal.NewFromInt(1)}},
		PaymentMethod:   "cash",
		Notes:           &notes,
		ShippingAddress: &addr,
		WarehouseID:     1,
	}, 42, "Buyer", "buyer@keluargamart.local")
	if err != nil {
		t.Fatalf("checkout: %v", err)
	}
	// The supervisor accepted it: ERP Confirm → invoice issued → invoiced.
	o.Status = "invoiced"
	fs.orders[o.ID] = o

	cashierCtx := auth.ToContext(context.Background(), &auth.User{ID: 7, Role: auth.RoleCashier}, 1)
	got, err := s.AdvanceFulfillment(cashierCtx, o.ID, "delivered")
	if err != nil {
		t.Fatalf("handover of an approved pickup must work, got: %v", err)
	}
	if got.Status != "delivered" {
		t.Fatalf("status = %s, want delivered", got.Status)
	}
	if !got.PaidAmount.Equal(got.TotalAmount) {
		t.Errorf("cash collected at the counter must settle the order: paid=%s total=%s", got.PaidAmount, got.TotalAmount)
	}
}

// The same jump must stay refused for a TRANSFER pickup: money has not arrived,
// so an approved-but-unpaid transfer order cannot leave the counter.
func TestHandoverFromInvoicedTransferPickupRefused(t *testing.T) {
	s := svc()
	fs := s.store.(*fakeStore)
	fs.stocks["1:1"] = &Stock{ID: 1, ProductID: 1, WarehouseID: 1, Quantity: decimal.NewFromInt(10)}

	addr := "[Ambil Sendiri di Toko] Gudang Pusat Medan · Pengambil: QA (0812)"
	notes := "[Metode: transfer]"
	o, err := s.PlaceCheckout(context.Background(), CheckoutInput{
		Items:           []CheckoutItemInput{{ProductID: 1, Quantity: decimal.NewFromInt(1)}},
		PaymentMethod:   "transfer",
		Notes:           &notes,
		ShippingAddress: &addr,
		WarehouseID:     1,
	}, 42, "Buyer", "buyer@keluargamart.local")
	if err != nil {
		t.Fatalf("checkout: %v", err)
	}
	o.Status = "invoiced"
	fs.orders[o.ID] = o

	cashierCtx := auth.ToContext(context.Background(), &auth.User{ID: 7, Role: auth.RoleCashier}, 1)
	if _, err := s.AdvanceFulfillment(cashierCtx, o.ID, "delivered"); err == nil {
		t.Fatal("an unpaid transfer pickup must not be handed over at the till")
	}
}

// Online/transfer pickup that is ALREADY PAID: cashier must be able to hand over
// from confirmed or pending_approval without getting "invalid order status".
func TestHandoverFromConfirmedPaidTransferPickup(t *testing.T) {
	s := svc()
	fs := s.store.(*fakeStore)
	fs.stocks["1:1"] = &Stock{ID: 1, ProductID: 1, WarehouseID: 1, Quantity: decimal.NewFromInt(10)}

	addr := "[Ambil Sendiri di Toko] Gudang Pusat Medan · Pengambil: QA (0812)"
	notes := "[Metode: gateway]"
	o, err := s.PlaceCheckout(context.Background(), CheckoutInput{
		Items:           []CheckoutItemInput{{ProductID: 1, Quantity: decimal.NewFromInt(1)}},
		PaymentMethod:   "transfer",
		Notes:           &notes,
		ShippingAddress: &addr,
		WarehouseID:     1,
	}, 42, "Buyer", "buyer@keluargamart.local")
	if err != nil {
		t.Fatalf("checkout: %v", err)
	}

	// Paid online via Midtrans/transfer (paid_amount == total_amount) and confirmed
	o.PaidAmount = o.TotalAmount
	o.Status = "confirmed"
	fs.orders[o.ID] = o

	cashierCtx := auth.ToContext(context.Background(), &auth.User{ID: 7, Role: auth.RoleCashier}, 1)
	got, err := s.AdvanceFulfillment(cashierCtx, o.ID, "delivered")
	if err != nil {
		t.Fatalf("paid transfer pickup handover must succeed, got err: %v", err)
	}
	if got.Status != "delivered" {
		t.Fatalf("status = %s, want delivered", got.Status)
	}
}

func TestHandoverFromPendingApprovalPaidOnlinePickup(t *testing.T) {
	s := svc()
	fs := s.store.(*fakeStore)
	fs.stocks["1:1"] = &Stock{ID: 1, ProductID: 1, WarehouseID: 1, Quantity: decimal.NewFromInt(10)}

	addr := "[Ambil Sendiri di Toko] Gudang Pusat Medan · Pengambil: QA (0812)"
	notes := "[Metode: gateway]"
	o, err := s.PlaceCheckout(context.Background(), CheckoutInput{
		Items:           []CheckoutItemInput{{ProductID: 1, Quantity: decimal.NewFromInt(1)}},
		PaymentMethod:   "transfer",
		Notes:           &notes,
		ShippingAddress: &addr,
		WarehouseID:     1,
	}, 42, "Buyer", "buyer@keluargamart.local")
	if err != nil {
		t.Fatalf("checkout: %v", err)
	}

	// Buyer paid online immediately, but supervisor hasn't confirmed yet (status = pending_approval)
	o.PaidAmount = o.TotalAmount
	o.Status = "pending_approval"
	fs.orders[o.ID] = o

	cashierCtx := auth.ToContext(context.Background(), &auth.User{ID: 7, Role: auth.RoleCashier}, 1)
	got, err := s.AdvanceFulfillment(cashierCtx, o.ID, "delivered")
	if err != nil {
		t.Fatalf("paid online pickup in pending_approval must be hand-overable at the till, got: %v", err)
	}
	if got.Status != "delivered" {
		t.Fatalf("status = %s, want delivered", got.Status)
	}
}
