package kb_test

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

	"github.com/stretchr/testify/require"
	kbservice "github.com/tidbcloud/AgentTeam/internal/service/kb"
	"github.com/tidbcloud/AgentTeam/internal/store/kb"
)

func TestKBHandlerKBKnowledgeRejectsActingUserAccessWithoutAgentGrant(t *testing.T) {
	wiki := &apiRecordingKBWikiReader{}
	mux, svc := newKBTestMuxAndServiceWithWiki(t, wiki)
	created := createKBKnowledgeKB(t, svc, "wsp_1", "admin-user", "Runbooks")
	readProfile := kb.KnowledgeBaseRepositoryAccessProfileRead
	_, err := svc.UpsertKnowledgeBasePermission(context.Background(), "wsp_1", "admin-user", created.ID, kbservice.KBPermissionGrantMutation{SubjectType: "user", SubjectID: "usr_human", Role: "view", RepositoryAccessProfile: &readProfile})
	require.NoError(t, err)

	agentAuth := "Bearer " + jwt(map[string]any{"sub": "agt_reader", "preferred_username": "mem-agent"})
	actingUserAuth := "Bearer " + jwt(map[string]any{"sub": "usr_human", "preferred_username": "human"})
	attestation := encodeAgentThreadAttestation(t, map[string]any{
		"workspace_id":        "wsp_1",
		"thread_channel_id":   "thr_kb",
		"agent_id":            "agt_reader",
		"acting_user_id":      "usr_human",
		"acting_member_id":    "mem_human",
		"acting_display_name": "Human Reviewer",
	})
	search := httptest.NewRequest(http.MethodPost, "/api/v1/kb/retrieval/knowledge/search", bytes.NewBufferString(`{"thread_channel_id":"thr_kb","query":"mcp","kb_ids":["`+created.ID+`"]}`))
	search.Header.Set("Authorization", agentAuth)
	search.Header.Set("X-Workspace-Id", "wsp_1")
	search.Header.Set("X-AgentTeam-Agent-Thread-Attestation", attestation)
	search.Header.Set("X-AgentTeam-Acting-User-Verified-JWT", actingUserAuth)
	searchRec := httptest.NewRecorder()
	mux.ServeHTTP(searchRec, search)

	require.Equal(t, http.StatusForbidden, searchRec.Code)
	require.Contains(t, searchRec.Body.String(), "knowledge base is not accessible to the selected agent")
	require.Empty(t, wiki.searchRequests)
}

func TestKBHandlerKBKnowledgeRejectsMismatchedActingUserAuthorization(t *testing.T) {
	wiki := &apiRecordingKBWikiReader{}
	mux, svc := newKBTestMuxAndServiceWithWiki(t, wiki)
	created := createKBKnowledgeKB(t, svc, "wsp_1", "admin-user", "Runbooks")
	readProfile := kb.KnowledgeBaseRepositoryAccessProfileRead
	_, err := svc.UpsertKnowledgeBasePermission(context.Background(), "wsp_1", "admin-user", created.ID, kbservice.KBPermissionGrantMutation{SubjectType: "user", SubjectID: "usr_human", Role: "view", RepositoryAccessProfile: &readProfile})
	require.NoError(t, err)

	attestation := encodeAgentThreadAttestation(t, map[string]any{
		"workspaceId":     "wsp_1",
		"threadChannelId": "thr_kb",
		"agentId":         "agt_reader",
		"actingUserId":    "usr_human",
	})
	search := httptest.NewRequest(http.MethodPost, "/api/v1/kb/retrieval/knowledge/search", bytes.NewBufferString(`{"threadChannelId":"thr_kb","query":"mcp","kbIds":["`+created.ID+`"]}`))
	search.Header.Set("Authorization", "Bearer "+jwt(map[string]any{"sub": "agt_reader"}))
	search.Header.Set("X-Workspace-Id", "wsp_1")
	search.Header.Set("X-AgentTeam-Agent-Thread-Attestation", attestation)
	search.Header.Set("X-AgentTeam-Acting-User-Verified-JWT", "Bearer "+jwt(map[string]any{"sub": "usr_other"}))
	searchRec := httptest.NewRecorder()
	mux.ServeHTTP(searchRec, search)

	require.Equal(t, http.StatusForbidden, searchRec.Code)
	require.Contains(t, searchRec.Body.String(), "AgentTeam acting user auth subject mismatch")
	require.Empty(t, wiki.searchRequests)
}
