package v1 import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "strconv" "testing" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/channel" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/sqlite" "gorm.io/gorm" "github.com/gochat/gochat/internal/service" ) func setupAgentBulkRouter(handler *AgentBulkHandler) *gin.Engine { gin.SetMode(gin.TestMode) r := gin.New() r.Use(gin.Recovery()) r.POST("/api/v1/accounts/:account_id/agents/bulk_assign", handler.BulkAssign) r.POST("/api/v1/accounts/:account_id/agents/bulk_unassign", handler.BulkUnassign) return r } func TestAgentBulkHandler_BulkAssign_BadJSON(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/1/agents/bulk_assign", bytes.NewReader([]byte("invalid json"))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandler_BulkAssign_EmptyConversationIDs(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) body := map[string]interface{}{ "conversation_ids": []uint{}, "agent_id": 10, } b, _ := json.Marshal(body) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/1/agents/bulk_assign", bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandler_BulkAssign_MissingAgentID(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) body := map[string]interface{}{ "conversation_ids": []uint{1, 2, 3}, } b, _ := json.Marshal(body) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/1/agents/bulk_assign", bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandler_BulkAssign_InvalidAccountID(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) body := map[string]interface{}{ "conversation_ids": []uint{1, 2}, "agent_id": 10, } b, _ := json.Marshal(body) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/abc/agents/bulk_assign", bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandlerBulkAssignRejectsInactiveAgent(t *testing.T) { db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{}) require.NoError(t, err) require.NoError(t, db.AutoMigrate(&model.Account{}, &model.User{}, &model.AccountUser{}, &model.Inbox{}, &model.Contact{}, &model.Conversation{})) account := &model.Account{Name: "Account"} agent := &model.User{Name: "Inactive", Email: "inactive@example.com", Password: "hash", Active: true} require.NoError(t, db.Create(account).Error) require.NoError(t, db.Create(agent).Error) require.NoError(t, db.Model(agent).Update("active", false).Error) require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: agent.ID, Role: "agent"}).Error) inbox := &model.Inbox{AccountID: account.ID, Name: "Inbox", ChannelType: string(model.InboxChannelTypeWebWidget)} contact := &model.Contact{AccountID: account.ID, Name: "Contact"} require.NoError(t, db.Create(inbox).Error) require.NoError(t, db.Create(contact).Error) conversation := &model.Conversation{AccountID: account.ID, InboxID: inbox.ID, ContactID: contact.ID, Status: "open", ChannelType: "web_widget", Channel: "web_widget"} require.NoError(t, db.Create(conversation).Error) conversationService := service.NewConversationService( repository.NewConversationRepo(db), repository.NewMessageRepo(db), channel.NewDispatcher(), nil, repository.NewAccountUserRepo(db), nil, nil, ) router := setupAgentBulkRouter(NewAgentBulkHandler(conversationService)) body, err := json.Marshal(map[string]any{"conversation_ids": []uint{conversation.ID}, "agent_id": agent.ID}) require.NoError(t, err) w := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/api/v1/accounts/"+strconv.FormatUint(uint64(account.ID), 10)+"/agents/bulk_assign", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) require.Equal(t, http.StatusOK, w.Code) require.Contains(t, w.Body.String(), "not an agent or administrator") } func TestAgentBulkHandler_BulkUnassign_BadJSON(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/1/agents/bulk_unassign", bytes.NewReader([]byte("invalid json"))) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandler_BulkUnassign_EmptyConversationIDs(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) body := map[string]interface{}{ "conversation_ids": []uint{}, } b, _ := json.Marshal(body) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/1/agents/bulk_unassign", bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestAgentBulkHandler_BulkUnassign_InvalidAccountID(t *testing.T) { handler := NewAgentBulkHandler(&service.ConversationService{}) router := setupAgentBulkRouter(handler) body := map[string]interface{}{ "conversation_ids": []uint{1, 2}, } b, _ := json.Marshal(body) w := httptest.NewRecorder() req, _ := http.NewRequest("POST", "/api/v1/accounts/abc/agents/bulk_unassign", bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) }