package sales

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/TaruLab/keluargamart-backend/internal/auth"
	"github.com/go-chi/chi/v5"
)

// buyerGuardTestSetup builds a handler with one order owned by customer 7 and
// two users: buyer-7 (owns it) and buyer-9 (does not).
func buyerGuardTestSetup(t *testing.T) (*Handler, *chi.Mux) {
	t.Helper()
	st := newFakeStore()
	st.orders[1] = &SalesOrder{ID: 1, CustomerID: 7, Status: "confirmed"}
	svc := NewService(st, nil, nil)
	h := NewHandler(svc)
	resolver := func(_ context.Context, userID int64) (int64, bool, error) {
		if userID == 100 {
			return 7, true, nil
		}
		return 9, true, nil
	}
	h.WithCustomerResolver(resolver)
	r := chi.NewRouter()
	r.Get("/orders/{id}", h.GetOrder)
	r.Delete("/orders/{id}", h.DeleteOrder)
	r.Post("/orders/{id}/cancel", h.CancelOrder)
	return h, r
}

func asBuyer(userID int64) context.Context {
	u := &auth.User{ID: userID, Role: auth.RoleBuyer}
	return auth.ToContext(context.Background(), u, 1)
}

func TestGetOrder_BuyerOwnsOrder(t *testing.T) {
	_, r := buyerGuardTestSetup(t)
	req := httptest.NewRequest(http.MethodGet, "/orders/1", nil).WithContext(asBuyer(100))
	rec := httptest.NewRecorder()
	r.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("owner GET = %d, want 200", rec.Code)
	}
}

func TestGetOrder_ForeignOrderNotFoundForBuyer(t *testing.T) {
	_, r := buyerGuardTestSetup(t)
	req := httptest.NewRequest(http.MethodGet, "/orders/1", nil).WithContext(asBuyer(999))
	rec := httptest.NewRecorder()
	r.ServeHTTP(rec, req)
	if rec.Code != http.StatusNotFound {
		t.Fatalf("foreign buyer GET = %d, want 404", rec.Code)
	}
}

func TestCancelOrder_ForeignOrderBlockedForBuyer(t *testing.T) {
	_, r := buyerGuardTestSetup(t)
	req := httptest.NewRequest(http.MethodPost, "/orders/1/cancel", nil).WithContext(asBuyer(999))
	rec := httptest.NewRecorder()
	r.ServeHTTP(rec, req)
	if rec.Code != http.StatusNotFound {
		t.Fatalf("foreign buyer cancel = %d, want 404", rec.Code)
	}
}

func TestGetOrder_StaffBypassesOwnershipGuard(t *testing.T) {
	// No auth user in context (staff paths go through RequirePermission which
	// guarantees an authenticated staff user): guard must not block.
	_, r := buyerGuardTestSetup(t)
	req := httptest.NewRequest(http.MethodGet, "/orders/1", nil)
	rec := httptest.NewRecorder()
	r.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("unscoped caller GET = %d, want 200", rec.Code)
	}
}
