Ctrl K
ComunidadGuías…

internal/handler/email_log_handler.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package handler

import (
	"net/http"
	"strconv"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/johnzastrow/actalog/internal/domain"
	"github.com/johnzastrow/actalog/internal/service"
	"github.com/johnzastrow/actalog/pkg/logger"
	"github.com/johnzastrow/actalog/pkg/middleware"
)

// EmailLogHandler handles email log endpoints
type EmailLogHandler struct {
	emailLogService *service.EmailLogService
	logger          *logger.Logger
}

// NewEmailLogHandler creates a new email log handler
func NewEmailLogHandler(emailLogService *service.EmailLogService, logger *logger.Logger) *EmailLogHandler {
	return &EmailLogHandler{
		emailLogService: emailLogService,
		logger:          logger,
	}
}

// ListEmailLogs handles GET /api/admin/email-logs
// Returns a paginated list of email logs with optional filters
func (h *EmailLogHandler) ListEmailLogs(w http.ResponseWriter, r *http.Request) {
	// Verify admin authorization
	_, ok := middleware.GetUserID(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "Unauthorized")
		return
	}

	// Parse query parameters
	query := r.URL.Query()

	// Pagination
	limit := 50
	offset := 0

	if limitStr := query.Get("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
			limit = l
		}
	}

	if offsetStr := query.Get("offset"); offsetStr != "" {
		if o, err := strconv.Atoi(offsetStr); err == nil && o >= 0 {
			offset = o
		}
	}

	// Build filters
	filters := domain.EmailLogFilters{}

	if emailType := query.Get("type"); emailType != "" {
		filters.EmailType = &emailType
	}

	if recipient := query.Get("recipient"); recipient != "" {
		filters.RecipientEmail = &recipient
	}

	if successStr := query.Get("success"); successStr != "" {
		if success, err := strconv.ParseBool(successStr); err == nil {
			filters.Success = &success
		}
	}

	if startDateStr := query.Get("start_date"); startDateStr != "" {
		if startDate, err := time.Parse("2006-01-02", startDateStr); err == nil {
			filters.StartDate = &startDate
		}
	}

	if endDateStr := query.Get("end_date"); endDateStr != "" {
		if endDate, err := time.Parse("2006-01-02", endDateStr); err == nil {
			// Add one day to include the end date
			endDate = endDate.Add(24 * time.Hour)
			filters.EndDate = &endDate
		}
	}

	// Get logs
	logs, err := h.emailLogService.List(filters, limit, offset)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to fetch email logs")
		return
	}

	// Get total count
	count, err := h.emailLogService.Count(filters)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to count email logs")
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"logs":   logs,
		"count":  count,
		"limit":  limit,
		"offset": offset,
	})
}

// GetEmailLog handles GET /api/admin/email-logs/{id}
// Returns a single email log by ID with full debug info
func (h *EmailLogHandler) GetEmailLog(w http.ResponseWriter, r *http.Request) {
	// Verify admin authorization
	_, ok := middleware.GetUserID(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "Unauthorized")
		return
	}

	// Get ID from URL
	idStr := chi.URLParam(r, "id")
	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		respondError(w, http.StatusBadRequest, "Invalid email log ID")
		return
	}

	// Get log
	log, err := h.emailLogService.GetByID(id)
	if err != nil {
		respondError(w, http.StatusNotFound, "Email log not found")
		return
	}

	respondJSON(w, http.StatusOK, log)
}

// GetEmailStats handles GET /api/admin/email-logs/stats
// Returns statistics about email logs
func (h *EmailLogHandler) GetEmailStats(w http.ResponseWriter, r *http.Request) {
	// Verify admin authorization
	_, ok := middleware.GetUserID(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "Unauthorized")
		return
	}

	stats, err := h.emailLogService.GetEmailStats()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to get email statistics")
		return
	}

	respondJSON(w, http.StatusOK, stats)
}

// CleanupEmailLogs handles POST /api/admin/email-logs/cleanup
// Removes email logs older than the retention period
func (h *EmailLogHandler) CleanupEmailLogs(w http.ResponseWriter, r *http.Request) {
	// Verify admin authorization
	_, ok := middleware.GetUserID(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "Unauthorized")
		return
	}

	// Use default retention period (90 days)
	deleted, err := h.emailLogService.CleanupOldLogs(service.EmailLogRetentionDays)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to cleanup email logs")
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"message":        "Email logs cleaned up successfully",
		"deleted_count":  deleted,
		"retention_days": service.EmailLogRetentionDays,
	})
}

// GetRecentFailures handles GET /api/admin/email-logs/failures
// Returns recent failed email attempts
func (h *EmailLogHandler) GetRecentFailures(w http.ResponseWriter, r *http.Request) {
	// Verify admin authorization
	_, ok := middleware.GetUserID(r.Context())
	if !ok {
		respondError(w, http.StatusUnauthorized, "Unauthorized")
		return
	}

	// Parse limit
	limit := 20
	if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
			limit = l
		}
	}

	failures, err := h.emailLogService.GetRecentFailures(limit)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "Failed to fetch recent failures")
		return
	}

	respondJSON(w, http.StatusOK, map[string]interface{}{
		"failures": failures,
		"count":    len(failures),
	})
}