package handlers import ( "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/ren/econ/backend/internal/models" "github.com/ren/econ/backend/internal/repository" "github.com/ren/econ/backend/internal/services" ) type UsersHandler struct { userRepo *repository.UserRepository progresoRepo *repository.ProgresoRepository authService *services.AuthService } func NewUsersHandler(userRepo *repository.UserRepository, progresoRepo *repository.ProgresoRepository, authService *services.AuthService) *UsersHandler { return &UsersHandler{ userRepo: userRepo, progresoRepo: progresoRepo, authService: authService, } } // ListUsers godoc // @Summary Listar usuarios // @Description Lista todos los usuarios (solo admin) // @Tags admin // @Produce json // @Security BearerAuth // @Success 200 {array} models.Usuario // @Router /api/admin/usuarios [get] func (h *UsersHandler) ListUsers(c *gin.Context) { users, err := h.userRepo.List(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al listar usuarios"}) return } if users == nil { users = []models.Usuario{} } c.JSON(http.StatusOK, users) } // CreateUser godoc // @Summary Crear usuario // @Description Crea un nuevo usuario (solo admin) // @Tags admin // @Accept json // @Produce json // @Param usuario body models.UsuarioCreate true "Usuario a crear" // @Security BearerAuth // @Success 201 {object} models.Usuario // @Router /api/admin/usuarios [post] func (h *UsersHandler) CreateUser(c *gin.Context) { var req models.UsuarioCreate if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Hash password if provided passwordHash := req.Password if passwordHash != "" { hash, err := h.authService.HashPassword(passwordHash) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al hashear password"}) return } passwordHash = hash } user := &models.Usuario{ Username: req.Username, Email: req.Email, PasswordHash: passwordHash, Nombre: req.Nombre, Rol: req.Rol, } // Si no se proporciona email, generar uno automáticamente basado en el username if user.Email == "" { user.Email = req.Username + "@econ.local" } if user.Rol == "" { user.Rol = "estudiante" } err := h.userRepo.Create(c.Request.Context(), user) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al crear usuario: " + err.Error()}) return } c.JSON(http.StatusCreated, user) } // GetUser godoc // @Summary Obtener usuario // @Description Obtiene un usuario por ID (solo admin) // @Tags admin // @Produce json // @Security BearerAuth // @Param id path string true "ID del usuario" // @Success 200 {object} models.Usuario // @Router /api/admin/usuarios/{id} [get] func (h *UsersHandler) GetUser(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido"}) return } user, err := h.userRepo.GetByID(c.Request.Context(), id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Usuario no encontrado"}) return } c.JSON(http.StatusOK, user) } // UpdateUser godoc // @Summary Actualizar usuario // @Description Actualiza un usuario (solo admin) // @Tags admin // @Accept json // @Produce json // @Param id path string true "ID del usuario" // @Param usuario body models.UsuarioUpdate true "Datos a actualizar" // @Security BearerAuth // @Success 200 {object} models.Usuario // @Router /api/admin/usuarios/{id} [put] func (h *UsersHandler) UpdateUser(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido"}) return } var req models.UsuarioUpdate if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userRepo.GetByID(c.Request.Context(), id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Usuario no encontrado"}) return } if req.Email != "" { user.Email = req.Email } if req.Nombre != "" { user.Nombre = req.Nombre } if req.Activo != nil { user.Activo = *req.Activo } err = h.userRepo.Update(c.Request.Context(), user) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al actualizar usuario"}) return } c.JSON(http.StatusOK, user) } // DeleteUser godoc // @Summary Eliminar usuario // @Description Desactiva un usuario (solo admin) // @Tags admin // @Produce json // @Security BearerAuth // @Param id path string true "ID del usuario" // @Success 200 {object} map[string]string // @Router /api/admin/usuarios/{id} [delete] func (h *UsersHandler) DeleteUser(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido"}) return } err = h.userRepo.Delete(c.Request.Context(), id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al eliminar usuario"}) return } c.JSON(http.StatusOK, gin.H{"message": "Usuario desactivado exitosamente"}) } // GetUserProgreso godoc // @Summary Ver progreso de usuario // @Description Obtiene el progreso de un usuario (solo admin) // @Tags admin // @Produce json // @Security BearerAuth // @Param id path string true "ID del usuario" // @Success 200 {array} models.Progreso // @Router /api/admin/usuarios/{id}/progreso [get] func (h *UsersHandler) GetUserProgreso(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido"}) return } progresos, err := h.progresoRepo.GetProgresoByUsuarioID(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al obtener progreso"}) return } if progresos == nil { progresos = []models.Progreso{} } c.JSON(http.StatusOK, progresos) }