package kb_test

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

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

func TestKBHandlerUpdatesRepositoryAccessProfileIndependently(t *testing.T) {
	mux, svc := newKBTestMuxAndServiceWithWiki(t, nil)
	ctx := context.Background()
	base, err := svc.CreateKnowledgeBase(ctx, "wsp_1", "owner", kb.KBMutation{Name: "Runbooks"})
	require.NoError(t, err)
	authHeader := "Bearer " + jwt(map[string]any{"sub": "owner"})

	createGrant := httptest.NewRequest(http.MethodPost, "/api/v1/kb/"+base.ID+"/permissions/grants", bytes.NewBufferString(`{
		"subjectType":"user",
		"subjectId":"viewer",
		"role":"view",
		"repositoryAccessProfile":"read"
	}`))
	createGrant.Header.Set("Authorization", authHeader)
	createGrant.Header.Set("X-Workspace-Id", "wsp_1")
	createGrantRec := httptest.NewRecorder()
	mux.ServeHTTP(createGrantRec, createGrant)
	require.Equal(t, http.StatusOK, createGrantRec.Code)
	var created struct {
		ID                      string `json:"id"`
		Role                    string `json:"role"`
		RepositoryAccessProfile string `json:"repositoryAccessProfile"`
		RepositoryAccessStatus  string `json:"repositoryAccessStatus"`
	}
	require.NoError(t, json.Unmarshal(createGrantRec.Body.Bytes(), &created))
	require.Equal(t, "view", created.Role)
	require.Equal(t, "read", created.RepositoryAccessProfile)
	require.Equal(t, "not_granted", created.RepositoryAccessStatus)

	profileOnly := httptest.NewRequest(http.MethodPatch, "/api/v1/kb/"+base.ID+"/permissions/grants/"+created.ID, bytes.NewBufferString(`{"repositoryAccessProfile":"write"}`))
	profileOnly.Header.Set("Authorization", authHeader)
	profileOnly.Header.Set("X-Workspace-Id", "wsp_1")
	profileOnlyRec := httptest.NewRecorder()
	mux.ServeHTTP(profileOnlyRec, profileOnly)
	require.Equal(t, http.StatusOK, profileOnlyRec.Code)
	var profileUpdated struct {
		Role                    string `json:"role"`
		RepositoryAccessProfile string `json:"repositoryAccessProfile"`
	}
	require.NoError(t, json.Unmarshal(profileOnlyRec.Body.Bytes(), &profileUpdated))
	require.Equal(t, "view", profileUpdated.Role)
	require.Equal(t, "write", profileUpdated.RepositoryAccessProfile)

	roleOnly := httptest.NewRequest(http.MethodPatch, "/api/v1/kb/"+base.ID+"/permissions/grants/"+created.ID, bytes.NewBufferString(`{"role":"edit"}`))
	roleOnly.Header.Set("Authorization", authHeader)
	roleOnly.Header.Set("X-Workspace-Id", "wsp_1")
	roleOnlyRec := httptest.NewRecorder()
	mux.ServeHTTP(roleOnlyRec, roleOnly)
	require.Equal(t, http.StatusOK, roleOnlyRec.Code)
	var roleUpdated struct {
		Role                    string `json:"role"`
		RepositoryAccessProfile string `json:"repositoryAccessProfile"`
	}
	require.NoError(t, json.Unmarshal(roleOnlyRec.Body.Bytes(), &roleUpdated))
	require.Equal(t, "edit", roleUpdated.Role)
	require.Equal(t, "write", roleUpdated.RepositoryAccessProfile)

	reconcile := httptest.NewRequest(http.MethodPost, "/api/v1/kb/"+base.ID+"/permissions/grants/"+created.ID+"/repository-access/reconcile", nil)
	reconcile.Header.Set("Authorization", authHeader)
	reconcile.Header.Set("X-Workspace-Id", "wsp_1")
	reconcileRec := httptest.NewRecorder()
	mux.ServeHTTP(reconcileRec, reconcile)
	require.Equal(t, http.StatusOK, reconcileRec.Code)
	require.Contains(t, reconcileRec.Body.String(), `"repositoryAccessProfile":"write"`)

	list := httptest.NewRequest(http.MethodGet, "/api/v1/kb/"+base.ID+"/permissions", nil)
	list.Header.Set("Authorization", authHeader)
	list.Header.Set("X-Workspace-Id", "wsp_1")
	listRec := httptest.NewRecorder()
	mux.ServeHTTP(listRec, list)
	require.Equal(t, http.StatusOK, listRec.Code)
	require.Contains(t, listRec.Body.String(), `"repositoryAccessProfile":"write"`)
	require.Contains(t, listRec.Body.String(), `"repositoryAccessStatus":"not_granted"`)
}
