package repository import ( "narasi-ahli-be/app/database" "narasi-ahli-be/app/database/entity" "narasi-ahli-be/app/module/chat/request" "narasi-ahli-be/utils/paginator" ) type chatRepository struct { DB *database.Database } type ChatRepository interface { // Chat Session methods GetAllChatSessions(userId uint, req request.ChatSessionQueryRequest) (chatSessions []*entity.ChatSessions, paging paginator.Pagination, err error) FindChatSessionByID(id uint) (chatSession *entity.ChatSessions, err error) FindChatSessionByUserAndID(userId uint, id uint) (chatSession *entity.ChatSessions, err error) CreateChatSession(chatSession *entity.ChatSessions) (result *entity.ChatSessions, err error) UpdateChatSession(id uint, chatSession *entity.ChatSessions) (err error) DeleteChatSession(id uint) (err error) // Chat Message methods GetAllChatMessages(req request.ChatMessageQueryRequest) (chatMessages []*entity.ChatMessages, paging paginator.Pagination, err error) FindChatMessageByID(id uint) (chatMessage *entity.ChatMessages, err error) FindChatMessageByUserAndID(userId uint, id uint) (chatMessage *entity.ChatMessages, err error) CreateChatMessage(chatMessage *entity.ChatMessages) (result *entity.ChatMessages, err error) UpdateChatMessage(id uint, chatMessage *entity.ChatMessages) (err error) DeleteChatMessage(id uint) (err error) // Chat Participant methods CreateChatParticipant(chatParticipant *entity.ChatParticipants) (result *entity.ChatParticipants, err error) FindChatParticipantsBySessionID(chatSessionID uint) (participants []*entity.ChatParticipants, err error) UpdateChatParticipant(id uint, chatParticipant *entity.ChatParticipants) (err error) DeleteChatParticipant(id uint) (err error) // Utility methods FindPersonalChatSession(userId1 uint, userId2 uint) (chatSession *entity.ChatSessions, err error) CheckUserInChatSession(userId uint, chatSessionID uint) (isParticipant bool, err error) } func NewChatRepository(db *database.Database) ChatRepository { return &chatRepository{ DB: db, } } // Chat Session Repository Methods func (_i *chatRepository) GetAllChatSessions(userId uint, req request.ChatSessionQueryRequest) (chatSessions []*entity.ChatSessions, paging paginator.Pagination, err error) { // Get chat sessions where user is a participant query := _i.DB.DB.Model(&entity.ChatSessions{}). Joins("INNER JOIN chat_participants cp ON chat_sessions.id = cp.chat_session_id"). Where("cp.user_id = ? AND cp.is_active = true", userId) // Apply filters if req.Type != nil { query = query.Where("chat_sessions.type = ?", *req.Type) } // Include relationships query = query.Preload("Creator"). Preload("Participants", "is_active = true"). Preload("Participants.User"). Preload("Messages", "is_deleted = false"). Preload("Messages.Sender") // Order by updated_at desc (most recent first) query = query.Order("chat_sessions.updated_at DESC") // Apply pagination var count int64 query.Count(&count) req.Pagination.Count = count req.Pagination = paginator.Paging(req.Pagination) err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&chatSessions).Error paging = *req.Pagination return } func (_i *chatRepository) FindChatSessionByID(id uint) (chatSession *entity.ChatSessions, err error) { err = _i.DB.DB.Preload("Creator"). Preload("Participants", "is_active = true"). Preload("Participants.User"). Preload("Messages", "is_deleted = false"). Preload("Messages.Sender"). First(&chatSession, id).Error return } func (_i *chatRepository) FindChatSessionByUserAndID(userId uint, id uint) (chatSession *entity.ChatSessions, err error) { // Check if user is participant in this chat session var isParticipant bool err = _i.DB.DB.Table("chat_participants"). Select("COUNT(*) > 0"). Where("chat_session_id = ? AND user_id = ? AND is_active = true", id, userId). Scan(&isParticipant).Error if err != nil { return nil, err } if !isParticipant { return nil, nil } err = _i.DB.DB.Preload("Creator"). Preload("Participants", "is_active = true"). Preload("Participants.User"). Preload("Messages", "is_deleted = false"). Preload("Messages.Sender"). First(&chatSession, id).Error return } func (_i *chatRepository) CreateChatSession(chatSession *entity.ChatSessions) (result *entity.ChatSessions, err error) { err = _i.DB.DB.Create(chatSession).Error if err != nil { return nil, err } // Reload with relationships err = _i.DB.DB.Preload("Creator"). Preload("Participants", "is_active = true"). Preload("Participants.User"). First(&result, chatSession.ID).Error return } func (_i *chatRepository) UpdateChatSession(id uint, chatSession *entity.ChatSessions) (err error) { err = _i.DB.DB.Model(&entity.ChatSessions{}).Where("id = ?", id).Updates(chatSession).Error return } func (_i *chatRepository) DeleteChatSession(id uint) (err error) { err = _i.DB.DB.Delete(&entity.ChatSessions{}, id).Error return } // Chat Message Repository Methods func (_i *chatRepository) GetAllChatMessages(req request.ChatMessageQueryRequest) (chatMessages []*entity.ChatMessages, paging paginator.Pagination, err error) { // Check if user is participant in this chat session var isParticipant bool err = _i.DB.DB.Table("chat_participants"). Select("COUNT(*) > 0"). Where("chat_session_id = ? AND user_id = ? AND is_active = true", req.ChatSessionID, req.UserID). Scan(&isParticipant).Error if err != nil { return nil, paginator.Pagination{}, err } if !isParticipant { return nil, paginator.Pagination{}, nil } query := _i.DB.DB.Model(&entity.ChatMessages{}).Where("chat_session_id = ? AND is_deleted = false", req.ChatSessionID) // Include relationships query = query.Preload("Sender") // Order by created_at desc (most recent first) query = query.Order("created_at DESC") // Apply pagination var count int64 query.Count(&count) req.Pagination.Count = count req.Pagination = paginator.Paging(req.Pagination) err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&chatMessages).Error paging = *req.Pagination return } func (_i *chatRepository) FindChatMessageByID(id uint) (chatMessage *entity.ChatMessages, err error) { err = _i.DB.DB.Preload("Sender").First(&chatMessage, id).Error return } func (_i *chatRepository) FindChatMessageByUserAndID(userId uint, id uint) (chatMessage *entity.ChatMessages, err error) { // Check if user is participant in the chat session of this message var isParticipant bool err = _i.DB.DB.Table("chat_messages cm"). Joins("INNER JOIN chat_participants cp ON cm.chat_session_id = cp.chat_session_id"). Select("COUNT(*) > 0"). Where("cm.id = ? AND cp.user_id = ? AND cp.is_active = true", id, userId). Scan(&isParticipant).Error if err != nil { return nil, err } if !isParticipant { return nil, nil } err = _i.DB.DB.Preload("Sender").First(&chatMessage, id).Error return } func (_i *chatRepository) CreateChatMessage(chatMessage *entity.ChatMessages) (result *entity.ChatMessages, err error) { err = _i.DB.DB.Create(chatMessage).Error if err != nil { return nil, err } // Reload with relationships err = _i.DB.DB.Preload("Sender").First(&result, chatMessage.ID).Error return } func (_i *chatRepository) UpdateChatMessage(id uint, chatMessage *entity.ChatMessages) (err error) { err = _i.DB.DB.Model(&entity.ChatMessages{}).Where("id = ?", id).Updates(chatMessage).Error return } func (_i *chatRepository) DeleteChatMessage(id uint) (err error) { err = _i.DB.DB.Delete(&entity.ChatMessages{}, id).Error return } // Chat Participant Repository Methods func (_i *chatRepository) CreateChatParticipant(chatParticipant *entity.ChatParticipants) (result *entity.ChatParticipants, err error) { err = _i.DB.DB.Create(chatParticipant).Error if err != nil { return nil, err } // Reload with relationships err = _i.DB.DB.Preload("User").First(&result, chatParticipant.ID).Error return } func (_i *chatRepository) FindChatParticipantsBySessionID(chatSessionID uint) (participants []*entity.ChatParticipants, err error) { err = _i.DB.DB.Model(&entity.ChatParticipants{}).Where("chat_session_id = ? AND is_active = true", chatSessionID). Preload("User").Find(&participants).Error return } func (_i *chatRepository) UpdateChatParticipant(id uint, chatParticipant *entity.ChatParticipants) (err error) { err = _i.DB.DB.Model(&entity.ChatParticipants{}).Where("id = ?", id).Updates(chatParticipant).Error return } func (_i *chatRepository) DeleteChatParticipant(id uint) (err error) { err = _i.DB.DB.Delete(&entity.ChatParticipants{}, id).Error return } // Utility Methods func (_i *chatRepository) FindPersonalChatSession(userId1 uint, userId2 uint) (chatSession *entity.ChatSessions, err error) { err = _i.DB.DB.Model(&entity.ChatSessions{}). Joins("INNER JOIN chat_participants cp1 ON chat_sessions.id = cp1.chat_session_id"). Joins("INNER JOIN chat_participants cp2 ON chat_sessions.id = cp2.chat_session_id"). Where("chat_sessions.type = 'personal' AND cp1.user_id = ? AND cp2.user_id = ? AND cp1.is_active = true AND cp2.is_active = true", userId1, userId2). Preload("Creator"). Preload("Participants", "is_active = true"). Preload("Participants.User"). First(&chatSession).Error return } func (_i *chatRepository) CheckUserInChatSession(userId uint, chatSessionID uint) (isParticipant bool, err error) { err = _i.DB.DB.Table("chat_participants"). Select("COUNT(*) > 0"). Where("chat_session_id = ? AND user_id = ? AND is_active = true", chatSessionID, userId). Scan(&isParticipant).Error return }