package auth

import "testing"

// RBAC audit 2026-08-25 — buyer is an E-COMMERCE application scope: its DB
// rows must never grant internal operator powers to a customer account.

func TestBuyerScopeIsMinimal(t *testing.T) {
	installRoleFixture(t)
	u := &User{ID: 4, Role: RoleBuyer}
	denied := []string{
		"sales.pos.create",               // POS terminal access
		"sales.sales-orders.view",        // company-wide order list
		"sales.sales-vouchers.view",      // company-wide voucher list
		"masterdata.products.create",     // global master-data write
		"masterdata.customers.read",      // customer directory (PII)
		"distribution.delivery-orders.view", // company-wide DO list
		"finance.reports.view",           // P&L / balance sheet / analytics
		"dashboard.view",                 // central dashboards
		"system.notifications.send",
		"inventory.stock.view",
	}
	for _, p := range denied {
		if u.Can(p) {
			t.Errorf("buyer must NOT hold %q", p)
		}
	}
	granted := []string{
		"cart.add",
		"cart.checkout",
		"galon.transactions.create",
		"sales.sales-vouchers.validate",
		"sales.sales-orders.cancel",
		"sales.returns.create",
		"distribution.tracking.lookup",
		"masterdata.products.read",
		"masterdata.memberships.read",
	}
	for _, p := range granted {
		if !u.Can(p) {
			t.Errorf("buyer must hold %q", p)
		}
	}
}

func TestReportGatesPerRole(t *testing.T) {
	installRoleFixture(t)
	finance := &User{ID: 1, Role: RoleFinance}
	if !finance.Can("finance.reports.view") || !finance.Can("dashboard.view") || !finance.Can("sales.reports.view") {
		t.Fatal("finance must read financial + sales reports and central dashboard")
	}
	sales := &User{ID: 2, Role: RoleSales}
	if !sales.Can("dashboard.pos.view") || !sales.Can("sales.reports.view") || !sales.Can("dashboard.view") {
		t.Fatal("sales role must reach POS dashboard and sales report")
	}
	if finance.Can("dashboard.pos.view") {
		t.Fatal("finance has no business on the POS terminal dashboard")
	}
	warehouse := &User{ID: 3, Role: RoleWarehouse}
	if !warehouse.Can("dashboard.view") || warehouse.Can("finance.reports.view") {
		t.Fatal("warehouse scope mismatch on reports")
	}
}

// A role resolves exactly its DB rows: a stale wide row cannot be rescued
// by defaults, and narrowing one role never widens another.
func TestMatrixRowsAreExclusive(t *testing.T) {
	restore := roleMatrix.Load()
	defer roleMatrix.Store(restore)

	SetRoleMatrix(map[Role][]string{
		RoleBuyer: {"cart.*"}, // deliberately narrowed by an operator
	})
	u := &User{ID: 9, Role: RoleBuyer}
	if !u.Can("cart.add") {
		t.Fatal("matrix grant lost")
	}
	if u.Can("masterdata.products.read") {
		t.Fatal("unlisted grant leaked through an explicit matrix override")
	}
}
