package handlers import ( "log" "net/http" templateHandlers "synlotto-website/internal/handlers/template" securityHelpers "synlotto-website/internal/helpers/security" templateHelpers "synlotto-website/internal/helpers/template" messagesStorage "synlotto-website/internal/storage/messages" "synlotto-website/internal/helpers" "synlotto-website/internal/platform/bootstrap" ) // Inbox: paginated list of messages func MessagesInboxHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { userID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } page := helpers.Atoi(r.URL.Query().Get("page")) if page < 1 { page = 1 } perPage := 10 totalCount := messagesStorage.GetInboxMessageCount(app.DB, userID) totalPages := (totalCount + perPage - 1) / perPage if totalPages == 0 { totalPages = 1 } messages := messagesStorage.GetInboxMessages(app.DB, userID, page, perPage) data := templateHandlers.BuildTemplateData(app, w, r) ctx := templateHelpers.TemplateContext(w, r, data) ctx["Messages"] = messages ctx["CurrentPage"] = page ctx["TotalPages"] = totalPages ctx["PageRange"] = templateHelpers.PageRange(page, totalPages) tmpl := templateHelpers.LoadTemplateFiles("messages.html", "web/templates/account/messages/index.html") if err := tmpl.ExecuteTemplate(w, "layout", ctx); err != nil { templateHelpers.RenderError(w, r, http.StatusInternalServerError) } } } // Read a single message (marks as read) func ReadMessageHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := helpers.Atoi(r.URL.Query().Get("id")) userID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } message, err := messagesStorage.GetMessageByID(app.DB, userID, id) if err != nil { log.Printf("❌ Message not found: %v", err) message = nil } else if message != nil && !message.IsRead { _ = messagesStorage.MarkMessageAsRead(app.DB, id, userID) } data := templateHandlers.BuildTemplateData(app, w, r) ctx := templateHelpers.TemplateContext(w, r, data) ctx["Message"] = message tmpl := templateHelpers.LoadTemplateFiles("read-message.html", "web/templates/account/messages/read.html") _ = tmpl.ExecuteTemplate(w, "layout", ctx) } } // Archive a message func ArchiveMessageHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := helpers.Atoi(r.URL.Query().Get("id")) userID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } if err := messagesStorage.ArchiveMessage(app.DB, userID, id); err != nil { templateHelpers.SetFlash(r, "Failed to archive message.") } else { templateHelpers.SetFlash(r, "Message archived.") } http.Redirect(w, r, "/account/messages", http.StatusSeeOther) } } // List archived messages (paged) func ArchivedMessagesHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { userID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } page := helpers.Atoi(r.URL.Query().Get("page")) if page < 1 { page = 1 } perPage := 10 messages := messagesStorage.GetArchivedMessages(app.DB, userID, page, perPage) hasMore := len(messages) == perPage data := templateHandlers.BuildTemplateData(app, w, r) ctx := templateHelpers.TemplateContext(w, r, data) ctx["Messages"] = messages ctx["Page"] = page ctx["HasMore"] = hasMore tmpl := templateHelpers.LoadTemplateFiles("archived.html", "web/templates/account/messages/archived.html") _ = tmpl.ExecuteTemplate(w, "layout", ctx) } } // Compose & send message func SendMessageHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: data := templateHandlers.BuildTemplateData(app, w, r) ctx := templateHelpers.TemplateContext(w, r, data) tmpl := templateHelpers.LoadTemplateFiles("send-message.html", "web/templates/account/messages/send.html") if err := tmpl.ExecuteTemplate(w, "layout", ctx); err != nil { templateHelpers.RenderError(w, r, http.StatusInternalServerError) } case http.MethodPost: senderID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } recipientID := helpers.Atoi(r.FormValue("recipient_id")) subject := r.FormValue("subject") body := r.FormValue("message") if err := messagesStorage.SendMessage(app.DB, senderID, recipientID, subject, body); err != nil { templateHelpers.SetFlash(r, "Failed to send message.") } else { templateHelpers.SetFlash(r, "Message sent.") } http.Redirect(w, r, "/account/messages", http.StatusSeeOther) default: templateHelpers.RenderError(w, r, http.StatusMethodNotAllowed) } } } // Restore an archived message func RestoreMessageHandler(app *bootstrap.App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := helpers.Atoi(r.URL.Query().Get("id")) userID, ok := securityHelpers.GetCurrentUserID(app.SessionManager, r) if !ok { templateHelpers.RenderError(w, r, http.StatusForbidden) return } if err := messagesStorage.RestoreMessage(app.DB, userID, id); err != nil { templateHelpers.SetFlash(r, "Failed to restore message.") } else { templateHelpers.SetFlash(r, "Message restored.") } http.Redirect(w, r, "/account/messages/archive", http.StatusSeeOther) } }