package repository import ( "narasi-ahli-be/app/database/entity" "narasi-ahli-be/app/module/communications/request" "narasi-ahli-be/utils/paginator" "time" "gorm.io/gorm" ) type communicationsRepository struct { DB *gorm.DB } type CommunicationsRepository interface { // Conversations GetUserConversations(userId uint, req request.ConversationsQueryRequest) (conversations []*entity.Conversations, paging paginator.Pagination, err error) FindConversationByParticipants(participant1ID, participant2ID uint) (conversation *entity.Conversations, err error) FindConversationByUserAndId(userId uint, conversationId uint) (conversation *entity.Conversations, err error) CreateConversation(conversation *entity.Conversations) (result *entity.Conversations, err error) UpdateConversationLastMessage(conversationId uint, lastMessageAt *time.Time) (err error) // Chat Messages GetConversationMessages(conversationId uint, req request.ChatMessagesQueryRequest) (messages []*entity.ChatMessages, paging paginator.Pagination, err error) CreateChatMessage(message *entity.ChatMessages) (result *entity.ChatMessages, err error) MarkMessageAsRead(messageId uint, userId uint) (err error) GetUnreadCount(conversationId uint, userId uint) (count int64, err error) } func NewCommunicationsRepository(db *gorm.DB) CommunicationsRepository { return &communicationsRepository{ DB: db, } } // Conversations methods func (_i *communicationsRepository) GetUserConversations(userId uint, req request.ConversationsQueryRequest) (conversations []*entity.Conversations, paging paginator.Pagination, err error) { query := _i.DB.Where("participant1_id = ? OR participant2_id = ?", userId, userId) // Include relationships query = query.Preload("Participant1").Preload("Participant2") // Order by last message time desc, then by created_at desc query = query.Order("last_message_at DESC NULLS LAST, 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(&conversations).Error paging = *req.Pagination return } func (_i *communicationsRepository) FindConversationByParticipants(participant1ID, participant2ID uint) (conversation *entity.Conversations, err error) { err = _i.DB.Where( "(participant1_id = ? AND participant2_id = ?) OR (participant1_id = ? AND participant2_id = ?)", participant1ID, participant2ID, participant2ID, participant1ID).Preload("Participant1").Preload("Participant2").First(&conversation).Error return } func (_i *communicationsRepository) FindConversationByUserAndId(userId uint, conversationId uint) (conversation *entity.Conversations, err error) { err = _i.DB.Where( "id = ? AND (participant1_id = ? OR participant2_id = ?)", conversationId, userId, userId).Preload("Participant1").Preload("Participant2").First(&conversation).Error return } func (_i *communicationsRepository) CreateConversation(conversation *entity.Conversations) (result *entity.Conversations, err error) { err = _i.DB.Create(conversation).Error if err != nil { return nil, err } // Reload with relationships err = _i.DB.Preload("Participant1").Preload("Participant2").First(&result, conversation.ID).Error return } func (_i *communicationsRepository) UpdateConversationLastMessage(conversationId uint, lastMessageAt *time.Time) (err error) { err = _i.DB.Model(&entity.Conversations{}).Where("id = ?", conversationId).Update("last_message_at", lastMessageAt).Error return } // Chat Messages methods func (_i *communicationsRepository) GetConversationMessages(conversationId uint, req request.ChatMessagesQueryRequest) (messages []*entity.ChatMessages, paging paginator.Pagination, err error) { query := _i.DB.Where("conversation_id = ?", conversationId) // Include sender relationship query = query.Preload("Sender") // Order by created_at asc (oldest first for chat) query = query.Order("created_at ASC") // 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(&messages).Error paging = *req.Pagination return } func (_i *communicationsRepository) CreateChatMessage(message *entity.ChatMessages) (result *entity.ChatMessages, err error) { err = _i.DB.Create(message).Error if err != nil { return nil, err } // Reload with relationships err = _i.DB.Preload("Sender").First(&result, message.ID).Error return } func (_i *communicationsRepository) MarkMessageAsRead(messageId uint, userId uint) (err error) { err = _i.DB.Model(&entity.ChatMessages{}).Where("id = ? AND sender_id != ?", messageId, userId).Update("is_read", true).Error return } func (_i *communicationsRepository) GetUnreadCount(conversationId uint, userId uint) (count int64, err error) { err = _i.DB.Model(&entity.ChatMessages{}).Where("conversation_id = ? AND sender_id != ? AND is_read = false", conversationId, userId).Count(&count).Error return }