package service import ( "errors" "fmt" "narasi-ahli-be/app/module/ai_chat/mapper" "narasi-ahli-be/app/module/ai_chat/repository" "narasi-ahli-be/app/module/ai_chat/request" "narasi-ahli-be/app/module/ai_chat/response" usersRepository "narasi-ahli-be/app/module/users/repository" "narasi-ahli-be/utils/paginator" utilSvc "narasi-ahli-be/utils/service" "github.com/rs/zerolog" ) type aiChatService struct { Repo repository.AIChatRepository UsersRepo usersRepository.UsersRepository Log zerolog.Logger } type AIChatService interface { // Sessions GetUserSessions(authToken string, req request.AIChatSessionsQueryRequest) (sessions []*response.AIChatSessionsResponse, paging paginator.Pagination, err error) GetSession(authToken string, sessionId uint) (session *response.AIChatSessionsResponse, err error) CreateSession(authToken string, req request.AIChatSessionsCreateRequest) (session *response.AIChatSessionsResponse, err error) UpdateSession(authToken string, sessionId uint, req request.AIChatSessionsUpdateRequest) (err error) DeleteSession(authToken string, sessionId uint) error ArchiveSession(authToken string, sessionId uint) error // Messages GetSessionMessages(authToken string, sessionId uint, req request.AIChatMessagesQueryRequest) (messages []*response.AIChatMessagesResponse, paging paginator.Pagination, err error) SendMessage(authToken string, sessionId uint, req request.AIChatMessagesCreateRequest) (message *response.AIChatMessagesResponse, err error) UpdateMessage(authToken string, sessionId uint, messageId uint, req request.AIChatMessagesUpdateRequest) (err error) DeleteMessage(authToken string, sessionId uint, messageId uint) error // Logs GetUserLogs(authToken string, req request.AIChatLogsQueryRequest) (logs []*response.AIChatLogsResponse, paging paginator.Pagination, err error) GetLog(authToken string, logId uint) (log *response.AIChatLogsResponse, err error) } func NewAIChatService(repo repository.AIChatRepository, usersRepo usersRepository.UsersRepository, log zerolog.Logger) AIChatService { return &aiChatService{ Repo: repo, UsersRepo: usersRepo, Log: log, } } // Sessions methods func (_i *aiChatService) GetUserSessions(authToken string, req request.AIChatSessionsQueryRequest) (sessions []*response.AIChatSessionsResponse, paging paginator.Pagination, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) results, paging, err := _i.Repo.GetUserSessions(userInfo.ID, req) if err != nil { return } for _, result := range results { sessions = append(sessions, mapper.AIChatSessionsResponseMapper(result)) } return } func (_i *aiChatService) GetSession(authToken string, sessionId uint) (session *response.AIChatSessionsResponse, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) result, err := _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return nil, err } return mapper.AIChatSessionsResponseMapper(result), nil } func (_i *aiChatService) CreateSession(authToken string, req request.AIChatSessionsCreateRequest) (session *response.AIChatSessionsResponse, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) entity := req.ToEntity() entity.UserID = userInfo.ID // Generate unique AI session ID entity.AISessionID = fmt.Sprintf("ai_session_%d_%d", userInfo.ID, entity.ID) result, err := _i.Repo.CreateSession(entity) if err != nil { return nil, err } return mapper.AIChatSessionsResponseMapper(result), nil } func (_i *aiChatService) UpdateSession(authToken string, sessionId uint, req request.AIChatSessionsUpdateRequest) (err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) _i.Log.Info().Interface("data", req).Msg("Updating AI chat session") // Check if session exists and belongs to user existing, err := _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return err } if existing == nil { return errors.New("AI chat session not found") } entity := req.ToEntity() return _i.Repo.UpdateSession(userInfo.ID, sessionId, entity) } func (_i *aiChatService) DeleteSession(authToken string, sessionId uint) error { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) _i.Log.Info().Uint("userId", userInfo.ID).Uint("sessionId", sessionId).Msg("Deleting AI chat session") // Check if session exists and belongs to user existing, err := _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return err } if existing == nil { return errors.New("AI chat session not found") } return _i.Repo.DeleteSession(userInfo.ID, sessionId) } func (_i *aiChatService) ArchiveSession(authToken string, sessionId uint) error { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) _i.Log.Info().Uint("userId", userInfo.ID).Uint("sessionId", sessionId).Msg("Archiving AI chat session") // Check if session exists and belongs to user existing, err := _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return err } if existing == nil { return errors.New("AI chat session not found") } // Update status to archived existing.Status = "archived" return _i.Repo.UpdateSession(userInfo.ID, sessionId, existing) } // Messages methods func (_i *aiChatService) GetSessionMessages(authToken string, sessionId uint, req request.AIChatMessagesQueryRequest) (messages []*response.AIChatMessagesResponse, paging paginator.Pagination, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) // Verify session belongs to user _, err = _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return nil, paginator.Pagination{}, err } results, paging, err := _i.Repo.GetSessionMessages(sessionId, req) if err != nil { return } for _, result := range results { messages = append(messages, mapper.AIChatMessagesResponseMapper(result)) } return } func (_i *aiChatService) SendMessage(authToken string, sessionId uint, req request.AIChatMessagesCreateRequest) (message *response.AIChatMessagesResponse, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) _i.Log.Info().Interface("data", req).Msg("Sending AI chat message") // Verify session belongs to user _, err = _i.Repo.FindSessionByUserAndId(userInfo.ID, req.SessionID) if err != nil { return nil, err } entity := req.ToEntity() result, err := _i.Repo.CreateMessage(entity) if err != nil { return nil, err } // Increment message count in session err = _i.Repo.IncrementMessageCount(req.SessionID) if err != nil { _i.Log.Error().Err(err).Msg("Failed to increment message count") } return mapper.AIChatMessagesResponseMapper(result), nil } // Update Message func (_i *aiChatService) UpdateMessage(authToken string, sessionId uint, messageId uint, req request.AIChatMessagesUpdateRequest) (err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) // Verify session belongs to user _, err = _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return err } entity := req.ToEntity() return _i.Repo.UpdateMessage(messageId, entity) } // Delete Message func (_i *aiChatService) DeleteMessage(authToken string, sessionId uint, messageId uint) error { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) // Verify session belongs to user _, err := _i.Repo.FindSessionByUserAndId(userInfo.ID, sessionId) if err != nil { return err } return _i.Repo.DeleteMessage(messageId) } // Logs methods func (_i *aiChatService) GetUserLogs(authToken string, req request.AIChatLogsQueryRequest) (logs []*response.AIChatLogsResponse, paging paginator.Pagination, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) results, paging, err := _i.Repo.GetUserLogs(userInfo.ID, req) if err != nil { return } for _, result := range results { logs = append(logs, mapper.AIChatLogsResponseMapper(result)) } return } func (_i *aiChatService) GetLog(authToken string, logId uint) (log *response.AIChatLogsResponse, err error) { userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) result, err := _i.Repo.FindLogByUserAndId(userInfo.ID, logId) if err != nil { return nil, err } return mapper.AIChatLogsResponseMapper(result), nil }