// handlers/user.go
package handlers

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"time"

	"api_bb/internal/models"
	"api_bb/internal/service"
	"api_bb/pkg/logger"
	"api_bb/pkg/middleware"
	"api_bb/pkg/utils"

	"go.uber.org/zap"
)

type UserHandler struct {
	logger      logger.LoggerInterface
	userService service.UserService
}

func NewUserHandler(userService service.UserService) *UserHandler {
	return &UserHandler{
		logger:      logger.NewWrapper(logger.Get().With(zap.String("handler", "user"))),
		userService: userService,
	}
}

type UserResponse struct {
	ID         uint      `json:"id"`
	Email      string    `json:"email"`
	FirstName  string    `json:"firstName"`
	LastName   string    `json:"lastName"`
	Avatar     string    `json:"avatar"`
	Phone      string    `json:"phone"`
	Experience string    `json:"experience"`
	Goals      string    `json:"goals"`
	Newsletter bool      `json:"newsletter"`
	Role       string    `json:"role"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

// GetUsers возвращает список всех пользователей
func (h *UserHandler) GetUsers(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling get users request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	// Получаем пользователя из контекста для проверки аутентификации
	_, ok := middleware.GetUserFromContext(r.Context())
	if !ok {
		h.logger.Warn("get users failed - authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
		return
	}

	// Получаем список пользователей из сервиса
	users, err := h.userService.GetAllUsers()
	if err != nil {
		h.logger.Error("failed to get users from service", zap.Error(err))
		utils.RespondWithError(w, http.StatusInternalServerError, "Failed to get users: "+err.Error())
		return
	}

	// Преобразуем в response формат
	var userResponses []UserResponse
	for _, user := range users {
		userResponses = append(userResponses, toUserResponse(&user))
	}

	h.logger.Info("users list retrieved successfully",
		zap.Int("users_count", len(userResponses)),
	)

	utils.RespondWithJSON(w, http.StatusOK, userResponses)
}

func (h *UserHandler) GetProfile(w http.ResponseWriter, r *http.Request) {

	h.logger.Info("handling get profile request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	user, ok := middleware.GetUserFromContext(r.Context())
	if !ok {
		h.logger.Warn("get profile failed - authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
		return
	}

	h.logger.Info("profile retrieved successfully",
		zap.Uint("user_id", user.ID),
		zap.String("email", user.Email),
		zap.String("avatar", user.Avatar),
	)

	utils.RespondWithJSON(w, http.StatusOK, toUserResponse(user))
}

type UpdateProfileRequest struct {
	FirstName  string `json:"firstName"`
	LastName   string `json:"lastName"`
	Phone      string `json:"phone"`
	Experience string `json:"experience"`
	Goals      string `json:"goals"`
	Newsletter bool   `json:"newsletter"`
}

func (h *UserHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {

	h.logger.Info("handling update profile request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	// Логируем тело запроса для отладки
	bodyBytes, err := io.ReadAll(r.Body)
	if err != nil {
		h.logger.Error("failed to read request body", zap.Error(err))
		utils.RespondWithError(w, http.StatusBadRequest, "Failed to read request body: "+err.Error())
		return
	}

	// Восстанавливаем тело для дальнейшего использования
	r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

	h.logger.Debug("raw request body", zap.String("body", string(bodyBytes)))

	// Получаем пользователя из контекста
	currentUser, ok := middleware.GetUserFromContext(r.Context())
	if !ok {
		h.logger.Warn("update profile failed - authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
		return
	}

	var req UpdateProfileRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		h.logger.Error("failed to decode JSON payload", zap.Error(err))
		utils.RespondWithError(w, http.StatusBadRequest, "Invalid request payload: "+err.Error())
		return
	}

	// Валидация обязательных полей
	if req.FirstName == "" {
		h.logger.Warn("update profile failed - first name required")
		utils.RespondWithError(w, http.StatusBadRequest, "First name is required")
		return
	}
	if req.LastName == "" {
		h.logger.Warn("update profile failed - last name required")
		utils.RespondWithError(w, http.StatusBadRequest, "Last name is required")
		return
	}

	h.logger.Info("updating user profile",
		zap.Uint("user_id", currentUser.ID),
		zap.String("first_name", req.FirstName),
		zap.String("last_name", req.LastName),
		zap.String("experience", req.Experience),
		zap.String("goals", req.Goals),
		zap.Bool("newsletter", req.Newsletter),
	)

	// Обновляем данные пользователя
	updatedUser := &models.User{
		ID:         currentUser.ID,
		FirstName:  req.FirstName,
		LastName:   req.LastName,
		Phone:      req.Phone,
		Experience: req.Experience,
		Goals:      req.Goals,
		Newsletter: req.Newsletter,
		UpdatedAt:  time.Now(),
	}

	// Сохраняем обновленные данные
	if err := h.userService.UpdateProfile(updatedUser); err != nil {
		h.logger.Error("failed to update profile in service",
			zap.Uint("user_id", currentUser.ID),
			zap.Error(err),
		)
		utils.RespondWithError(w, http.StatusInternalServerError, "Failed to update profile: "+err.Error())
		return
	}

	h.logger.Info("profile updated successfully",
		zap.Uint("user_id", currentUser.ID),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
		"message": "Profile updated successfully",
		"user":    toUserResponse(updatedUser),
	})
}