// handlers/email_handler.go
package handlers

import (
	"net/http"

	"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 EmailHandler struct {
	logger       logger.LoggerInterface
	emailService *service.EmailService
}

func NewEmailHandler(emailService *service.EmailService) *EmailHandler {
	return &EmailHandler{
		logger:       logger.NewWrapper(logger.Get().With(zap.String("handler", "email"))),
		emailService: emailService,
	}
}

// VerifyEmail подтверждает email пользователя
func (h *EmailHandler) VerifyEmail(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling email verification request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	token := r.URL.Query().Get("token")
	if token == "" {
		h.logger.Warn("email verification failed - token is required")
		utils.RespondWithError(w, http.StatusBadRequest, "Токен обязателен")
		return
	}

	if err := h.emailService.VerifyEmail(token); err != nil {
		h.logger.Error("email verification failed, expired",
			zap.Error(err),
			zap.String("token", token),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Неверный или просроченный токен")
		return
	}

	h.logger.Info("email successfully verified",
		zap.String("token", token),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]string{
		"message": "Email успешно подтвержден",
	})
}

// RequestPasswordReset запрашивает сброс пароля
func (h *EmailHandler) RequestPasswordReset(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling password reset request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	var req models.PasswordResetRequest
	if err := utils.DecodeJSONBody(w, r, &req); err != nil {
		h.logger.Warn("password reset request failed - invalid request format",
			zap.Error(err),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
		return
	}

	if err := h.emailService.SendPasswordResetEmail(req.Email); err != nil {
		h.logger.Error("password reset request failed",
			zap.Error(err),
			zap.String("email", req.Email),
		)
		// Для безопасности всегда возвращаем успех
	}

	h.logger.Info("password reset request processed",
		zap.String("email", req.Email),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]string{
		"message": "Если email зарегистрирован, инструкции по восстановлению пароля будут отправлены",
	})
}

// ConfirmPasswordReset подтверждает сброс пароля
func (h *EmailHandler) ConfirmPasswordReset(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling password reset confirmation request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	var req models.PasswordResetConfirm
	if err := utils.DecodeJSONBody(w, r, &req); err != nil {
		h.logger.Warn("password reset confirmation failed - invalid request format",
			zap.Error(err),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
		return
	}

	if err := h.emailService.ResetPassword(req.Token, req.Password); err != nil {
		h.logger.Error("password reset confirmation failed",
			zap.Error(err),
			zap.String("token", req.Token),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Неверный или просроченный токен")
		return
	}

	h.logger.Info("password successfully reset",
		zap.String("token", req.Token),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]string{
		"message": "Пароль успешно изменен",
	})
}

type NewsletterRequest struct {
	Subject string `json:"subject" validate:"required"`
	Content string `json:"content" validate:"required"`
}

// SendNewsletter отправляет рассылку новостей
func (h *EmailHandler) SendNewsletter(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling newsletter sending request",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	var req NewsletterRequest
	if err := utils.DecodeJSONBody(w, r, &req); err != nil {
		h.logger.Warn("newsletter sending failed - invalid request format",
			zap.Error(err),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Неверный формат запроса")
		return
	}

	if err := h.emailService.SendNewsletterToSubscribers(req.Subject, req.Content); err != nil {
		h.logger.Error("newsletter sending failed",
			zap.Error(err),
			zap.String("subject", req.Subject),
		)
		utils.RespondWithError(w, http.StatusInternalServerError, "Не удалось отправить рассылку")
		return
	}

	h.logger.Info("newsletter sent successfully",
		zap.String("subject", req.Subject),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]string{
		"message": "Рассылка отправлена подписчикам",
	})
}

// ResendVerification повторно отправляет email верификации
func (h *EmailHandler) ResendVerification(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("handling resend verification 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("resend verification failed - authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Пользователь не авторизован")
		return
	}

	// Получаем пользователя
	userData, err := h.emailService.GetUserByID(user.ID)
	if err != nil {
		h.logger.Warn("resend verification failed - user not found",
			zap.Uint("user_id", user.ID),
			zap.Error(err),
		)
		utils.RespondWithError(w, http.StatusNotFound, "Пользователь не найден")
		return
	}

	if userData.EmailVerified {
		h.logger.Warn("resend verification failed - email already verified",
			zap.Uint("user_id", user.ID),
			zap.String("email", userData.Email),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Email уже подтвержден")
		return
	}

	if err := h.emailService.SendVerificationEmail(userData.ID, userData.Email, userData.FirstName); err != nil {
		h.logger.Error("resend verification failed",
			zap.Error(err),
			zap.Uint("user_id", user.ID),
			zap.String("email", userData.Email),
		)
		utils.RespondWithError(w, http.StatusInternalServerError, "Не удалось отправить email подтверждения")
		return
	}

	h.logger.Info("verification email resent successfully",
		zap.Uint("user_id", user.ID),
		zap.String("email", userData.Email),
	)

	utils.RespondWithJSON(w, http.StatusOK, map[string]string{
		"message": "Email подтверждения отправлен повторно",
	})
}
