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/services"
)

type AuthHandler struct {
	authService *services.AuthService
}

func NewAuthHandler(authService *services.AuthService) *AuthHandler {
	return &AuthHandler{authService: authService}
}

// Login godoc
// @Summary Iniciar sesión
// @Description Autentica usuario y devuelve tokens JWT
// @Tags auth
// @Accept json
// @Produce json
// @Param login body models.LoginRequest true "Credenciales"
// @Success 200 {object} models.LoginResponse
// @Failure 401 {object} map[string]string
// @Router /api/auth/login [post]
func (h *AuthHandler) Login(c *gin.Context) {
	var req models.LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	resp, err := h.authService.Login(c.Request.Context(), &req)
	if err != nil {
		switch err {
		case services.ErrInvalidCredentials:
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Credenciales inválidas"})
		case services.ErrUserInactive:
			c.JSON(http.StatusForbidden, gin.H{"error": "Usuario inactivo"})
		default:
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Error interno"})
		}
		return
	}

	c.JSON(http.StatusOK, resp)
}

// RefreshToken godoc
// @Summary Renovar token de acceso
// @Description Renueva el token de acceso usando el refresh token
// @Tags auth
// @Accept json
// @Produce json
// @Param refresh body models.RefreshRequest true "Refresh token"
// @Success 200 {object} models.LoginResponse
// @Failure 401 {object} map[string]string
// @Router /api/auth/refresh [post]
func (h *AuthHandler) RefreshToken(c *gin.Context) {
	var req models.RefreshRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	resp, err := h.authService.RefreshToken(c.Request.Context(), req.RefreshToken)
	if err != nil {
		switch err {
		case services.ErrInvalidToken, services.ErrTokenExpired:
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Token inválido o expirado"})
		case services.ErrUserNotFound:
			c.JSON(http.StatusNotFound, gin.H{"error": "Usuario no encontrado"})
		case services.ErrUserInactive:
			c.JSON(http.StatusForbidden, gin.H{"error": "Usuario inactivo"})
		default:
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Error interno"})
		}
		return
	}

	c.JSON(http.StatusOK, resp)
}

// Logout godoc
// @Summary Cerrar sesión
// @Description Cierra la sesión del usuario
// @Tags auth
// @Produce json
// @Security BearerAuth
// @Success 200 {object} map[string]string
// @Router /api/auth/logout [post]
func (h *AuthHandler) Logout(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "No autorizado"})
		return
	}

	err := h.authService.Logout(c.Request.Context(), userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al cerrar sesión"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Sesión cerrada exitosamente"})
}
