package middleware

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

	"kra/internal/biz"
	"kra/internal/conf"

	"github.com/gin-gonic/gin"
)

type accessControllerStub struct {
	scopeErr error
}

func (*accessControllerStub) Authorize(context.Context, uint, string, string) (bool, error) {
	return true, nil
}

func (s *accessControllerStub) ContextWithDataScope(ctx context.Context, authorityID, userID uint) (context.Context, error) {
	if s.scopeErr != nil {
		return ctx, s.scopeErr
	}
	return biz.NewDataScopeContext(ctx, biz.DataScope{UserID: userID, AuthorityID: authorityID, Scope: 1, All: true}), nil
}

func TestAccessControlFailsClosedWhenDataScopeResolutionFails(t *testing.T) {
	gin.SetMode(gin.TestMode)
	engine := gin.New()
	engine.Use(func(c *gin.Context) {
		c.Set(claimsKey, &biz.AuthClaims{ID: 7, AuthorityID: 888})
		c.Next()
	})
	engine.Use(AccessControl(conf.NewRuntime(nil, &conf.AdminBackend{}), &accessControllerStub{scopeErr: errors.New("database unavailable")}))
	called := false
	engine.GET("/protected", func(c *gin.Context) { called = true })

	response := httptest.NewRecorder()
	engine.ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/protected", nil))
	if called {
		t.Fatal("protected handler ran after data-scope resolution failed")
	}
	if response.Code != http.StatusOK || !strings.Contains(response.Body.String(), "数据权限解析失败") {
		t.Fatalf("status=%d body=%s", response.Code, response.Body.String())
	}
}
