package handlers

import (
	"context"
	"fmt"
	"net/http"

	apperrors "veza-backend-api/internal/errors"
	"veza-backend-api/internal/models"
	"veza-backend-api/internal/services"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

// ChatServiceInterfaceForChatHandler defines methods needed for chat handler
type ChatServiceInterfaceForChatHandler interface {
	GenerateToken(userID uuid.UUID, username string) (*services.ChatTokenResponse, error)
	GetStats(ctx context.Context) (*services.ChatStats, error)
}

// UserServiceInterfaceForChatHandler defines methods needed for chat handler
type UserServiceInterfaceForChatHandler interface {
	GetByID(userID uuid.UUID) (*models.User, error)
}

type ChatHandler struct {
	chatService ChatServiceInterfaceForChatHandler
	userService UserServiceInterfaceForChatHandler
	logger      *zap.Logger
}

func NewChatHandler(chatService *services.ChatService, userService *services.UserService, logger *zap.Logger) *ChatHandler {
	return &ChatHandler{
		chatService: &chatServiceWrapper{chatService: chatService},
		userService: &userServiceWrapper{userService: userService},
		logger:      logger,
	}
}

// chatServiceWrapper wraps *services.ChatService to implement ChatServiceInterfaceForChatHandler
type chatServiceWrapper struct {
	chatService *services.ChatService
}

func (w *chatServiceWrapper) GenerateToken(userID uuid.UUID, username string) (*services.ChatTokenResponse, error) {
	return w.chatService.GenerateToken(userID, username)
}

func (w *chatServiceWrapper) GetStats(ctx context.Context) (*services.ChatStats, error) {
	return w.chatService.GetStats(ctx)
}

// userServiceWrapper wraps *services.UserService to implement UserServiceInterfaceForChatHandler
type userServiceWrapper struct {
	userService *services.UserService
}

func (w *userServiceWrapper) GetByID(userID uuid.UUID) (*models.User, error) {
	return w.userService.GetByID(userID)
}

// NewChatHandlerWithInterface creates a new chat handler with interfaces (for testing)
func NewChatHandlerWithInterface(chatService ChatServiceInterfaceForChatHandler, userService UserServiceInterfaceForChatHandler, logger *zap.Logger) *ChatHandler {
	return &ChatHandler{
		chatService: chatService,
		userService: userService,
		logger:      logger,
	}
}

// GetToken generates a JWT token for the chat service
// @Summary      Get Chat Token
// @Description  Generate a short-lived token for chat authentication
// @Tags         Chat
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  APIResponse{data=object{token=string}}
// @Failure      401  {object}  APIResponse "Unauthorized"
// @Failure      500  {object}  APIResponse "Internal Error"
// @Router       /chat/token [get]
func (h *ChatHandler) GetToken(c *gin.Context) {
	userIDVal, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}
	userID, ok := userIDVal.(uuid.UUID)
	if !ok || userID == uuid.Nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}

	// Get username from DB
	user, err := h.userService.GetByID(userID)
	username := "user"
	if err == nil && user != nil {
		username = user.Username
	} else {
		// Fallback
		username = fmt.Sprintf("user_%s", userID)
	}

	token, err := h.chatService.GenerateToken(userID, username)
	if err != nil {
		h.logger.Error("Failed to generate chat token", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
		return
	}

	RespondSuccess(c, http.StatusOK, token)
}

// GetStats returns chat statistics
// BE-API-006: Implement chat stats endpoint
func (h *ChatHandler) GetStats(c *gin.Context) {
	stats, err := h.chatService.GetStats(c.Request.Context())
	if err != nil {
		h.logger.Error("Failed to get chat stats", zap.Error(err))
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get chat stats", err))
		return
	}

	RespondSuccess(c, http.StatusOK, stats)
}
