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)
}
