package web import ( "billit/internal/auth" "billit/internal/database" "net/http" "github.com/labstack/echo/v4" ) // AccountHandlers holds references for account operations type AccountHandlers struct { db database.Service auth *auth.Service } // NewAccountHandlers creates handlers with db and auth access func NewAccountHandlers(db database.Service, authService *auth.Service) *AccountHandlers { return &AccountHandlers{db: db, auth: authService} } // AccountPageHandler renders the /account page func (h *AccountHandlers) AccountPageHandler(c echo.Context) error { userID := getUserID(c) if userID == "" { return c.Redirect(http.StatusFound, "/") } user, err := h.db.GetUserByID(userID) if err != nil || user == nil { return RenderServerError(c, "Failed to load account details.") } return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "")) } // UpdateDetailsHandler handles POST /account/details func (h *AccountHandlers) UpdateDetailsHandler(c echo.Context) error { userID := getUserID(c) if userID == "" { return c.Redirect(http.StatusFound, "/") } user, err := h.db.GetUserByID(userID) if err != nil || user == nil { return RenderServerError(c, "Failed to load account details.") } companyDetails := c.FormValue("company_details") bankDetails := c.FormValue("bank_details") invoicePrefix := c.FormValue("invoice_prefix") if invoicePrefix == "" { invoicePrefix = "INV" // Default prefix } err = h.db.UpdateUserDetails(userID, companyDetails, bankDetails, invoicePrefix) if err != nil { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "Failed to update details")) } return Render(c, AccountPage(user.Email, user.CreatedAt, companyDetails, bankDetails, invoicePrefix, "Details updated successfully", "")) } // ChangePasswordHandler handles POST /account/password func (h *AccountHandlers) ChangePasswordHandler(c echo.Context) error { userID := getUserID(c) if userID == "" { return c.Redirect(http.StatusFound, "/") } user, err := h.db.GetUserByID(userID) if err != nil || user == nil { return RenderServerError(c, "Failed to load account details.") } currentPassword := c.FormValue("current_password") newPassword := c.FormValue("new_password") confirmPassword := c.FormValue("confirm_password") // Validate current password if !auth.CheckPassword(currentPassword, user.Password) { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "Current password is incorrect")) } // Validate new password if len(newPassword) < 8 { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "New password must be at least 8 characters")) } if newPassword != confirmPassword { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "New passwords do not match")) } // Hash new password hash, err := auth.HashPassword(newPassword) if err != nil { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "Failed to update password")) } // Update password in database err = h.db.UpdateUserPassword(userID, hash) if err != nil { return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "", "Failed to update password")) } return Render(c, AccountPage(user.Email, user.CreatedAt, user.CompanyDetails, user.BankDetails, user.InvoicePrefix, "Password changed successfully", "")) }