package handlers

import (
	"encoding/json"
	"net/http"
	"strconv"

	"git.kirlllll.ru/volontery/backend/internal/api/middleware"
	"git.kirlllll.ru/volontery/backend/internal/service"
	"github.com/go-chi/chi/v5"
)

// UserHandler обрабатывает запросы пользователей
type UserHandler struct {
	userService *service.UserService
}

// NewUserHandler создает новый UserHandler
func NewUserHandler(userService *service.UserService) *UserHandler {
	return &UserHandler{
		userService: userService,
	}
}

// GetProfile возвращает профиль пользователя
// GET /api/v1/users/{id}
func (h *UserHandler) GetProfile(w http.ResponseWriter, r *http.Request) {
	idStr := chi.URLParam(r, "id")
	userID, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		respondError(w, http.StatusBadRequest, "invalid user id")
		return
	}

	profile, err := h.userService.GetUserProfile(r.Context(), userID)
	if err != nil {
		respondError(w, http.StatusNotFound, "user not found")
		return
	}

	respondJSON(w, http.StatusOK, profile)
}

// GetMyProfile возвращает профиль текущего пользователя
// GET /api/v1/users/me
func (h *UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	profile, err := h.userService.GetUserProfile(r.Context(), userID)
	if err != nil {
		respondError(w, http.StatusNotFound, "user not found")
		return
	}

	respondJSON(w, http.StatusOK, profile)
}

// UpdateProfile обновляет профиль текущего пользователя
// PATCH /api/v1/users/me
func (h *UserHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	var input service.UpdateProfileInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		respondError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if err := h.userService.UpdateUserProfile(r.Context(), userID, input); err != nil {
		respondError(w, http.StatusInternalServerError, "failed to update profile")
		return
	}

	respondJSON(w, http.StatusOK, map[string]string{"message": "profile updated successfully"})
}

// UpdateLocation обновляет местоположение пользователя
// POST /api/v1/users/me/location
func (h *UserHandler) UpdateLocation(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	var input struct {
		Latitude  float64 `json:"latitude"`
		Longitude float64 `json:"longitude"`
	}

	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		respondError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if err := h.userService.UpdateUserLocation(r.Context(), userID, input.Latitude, input.Longitude); err != nil {
		respondError(w, http.StatusBadRequest, err.Error())
		return
	}

	respondJSON(w, http.StatusOK, map[string]string{"message": "location updated successfully"})
}

// GetMyRoles возвращает роли текущего пользователя
// GET /api/v1/users/me/roles
func (h *UserHandler) GetMyRoles(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	roles, err := h.userService.GetUserRoles(r.Context(), userID)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get roles")
		return
	}

	respondJSON(w, http.StatusOK, roles)
}

// GetMyPermissions возвращает разрешения текущего пользователя
// GET /api/v1/users/me/permissions
func (h *UserHandler) GetMyPermissions(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	permissions, err := h.userService.GetUserPermissions(r.Context(), userID)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to get permissions")
		return
	}

	respondJSON(w, http.StatusOK, permissions)
}

// VerifyEmail подтверждает email пользователя
// POST /api/v1/users/me/verify-email
func (h *UserHandler) VerifyEmail(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	// В реальной системе здесь должна быть проверка токена из письма
	// Сейчас просто подтверждаем email для текущего пользователя
	if err := h.userService.VerifyEmail(r.Context(), userID); err != nil {
		respondError(w, http.StatusInternalServerError, "failed to verify email")
		return
	}

	respondJSON(w, http.StatusOK, map[string]string{"message": "email verified successfully"})
}

// CheckPermission проверяет наличие разрешения у пользователя
// GET /api/v1/users/me/permissions/{permission_name}/check
func (h *UserHandler) CheckPermission(w http.ResponseWriter, r *http.Request) {
	userID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	permissionName := chi.URLParam(r, "permission_name")
	if permissionName == "" {
		respondError(w, http.StatusBadRequest, "permission_name is required")
		return
	}

	hasPermission, err := h.userService.HasPermission(r.Context(), userID, permissionName)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to check permission")
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"has_permission":  hasPermission,
		"permission_name": permissionName,
	})
}

// ========== AdminHandler - новый хендлер для административных функций ==========

// AdminHandler обрабатывает административные запросы
type AdminHandler struct {
	userService *service.UserService
}

// NewAdminHandler создает новый AdminHandler
func NewAdminHandler(userService *service.UserService) *AdminHandler {
	return &AdminHandler{
		userService: userService,
	}
}

// AssignRole назначает роль пользователю
// POST /api/v1/admin/users/{user_id}/roles/{role_id}
func (h *AdminHandler) AssignRole(w http.ResponseWriter, r *http.Request) {
	adminID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	// Проверка, что текущий пользователь является администратором
	// В реальной системе это должно быть в middleware
	isAdmin, err := h.userService.HasPermission(r.Context(), adminID, "manage_users")
	if err != nil {
		respondError(w, http.StatusInternalServerError, "failed to check permissions")
		return
	}
	if !isAdmin {
		respondError(w, http.StatusForbidden, "admin role required")
		return
	}

	userIDStr := chi.URLParam(r, "user_id")
	userID, err := strconv.ParseInt(userIDStr, 10, 64)
	if err != nil {
		respondError(w, http.StatusBadRequest, "invalid user_id")
		return
	}

	roleIDStr := chi.URLParam(r, "role_id")
	roleID, err := strconv.ParseInt(roleIDStr, 10, 64)
	if err != nil {
		respondError(w, http.StatusBadRequest, "invalid role_id")
		return
	}

	if err := h.userService.AssignRole(r.Context(), userID, roleID, adminID); err != nil {
		respondError(w, http.StatusBadRequest, err.Error())
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"message": "role assigned successfully",
		"user_id": userID,
		"role_id": roleID,
	})
}

// ========== RequestHandler - дополнительный метод ==========

// ModerateRequestProcedure модерирует заявку через stored procedure
// POST /api/v1/moderation/requests/{id}/moderate
func (h *RequestHandler) ModerateRequestProcedure(w http.ResponseWriter, r *http.Request) {
	moderatorID, ok := middleware.GetUserIDFromContext(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "unauthorized")
		return
	}

	idStr := chi.URLParam(r, "id")
	requestID, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		respondError(w, http.StatusBadRequest, "invalid request id")
		return
	}

	var input struct {
		Action  string  `json:"action"`
		Comment *string `json:"comment"`
	}

	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		respondError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if input.Action != "approve" && input.Action != "reject" {
		respondError(w, http.StatusBadRequest, "action must be 'approve' or 'reject'")
		return
	}

	if input.Action == "reject" && (input.Comment == nil || *input.Comment == "") {
		respondError(w, http.StatusBadRequest, "comment is required when rejecting")
		return
	}

	result, err := h.requestService.ModerateRequestProcedure(r.Context(), requestID, moderatorID, input.Action, input.Comment)
	if err != nil {
		respondError(w, http.StatusBadRequest, err.Error())
		return
	}

	if !result.Success {
		respondError(w, http.StatusBadRequest, result.Message)
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"success": result.Success,
		"message": result.Message,
	})
}
