// File Path: monorepo/cloud/maplepress-backend/internal/interface/http/handler/gateway/refresh_handler.go
package gateway

import (
	"net/http"

	"go.uber.org/zap"

	gatewaydto "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/dto/gateway"
	gatewaysvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/gateway"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httperror"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httpresponse"
)

// RefreshTokenHandler handles HTTP requests for token refresh
type RefreshTokenHandler struct {
	refreshTokenService gatewaysvc.RefreshTokenService
	logger              *zap.Logger
}

// NewRefreshTokenHandler creates a new refresh token handler
func NewRefreshTokenHandler(
	refreshTokenService gatewaysvc.RefreshTokenService,
	logger *zap.Logger,
) *RefreshTokenHandler {
	return &RefreshTokenHandler{
		refreshTokenService: refreshTokenService,
		logger:              logger.Named("refresh-token-handler"),
	}
}

// ProvideRefreshTokenHandler creates a new RefreshTokenHandler for dependency injection
func ProvideRefreshTokenHandler(
	refreshTokenService gatewaysvc.RefreshTokenService,
	logger *zap.Logger,
) *RefreshTokenHandler {
	return NewRefreshTokenHandler(refreshTokenService, logger)
}

// Handle processes POST /api/v1/refresh requests
// CWE-613: Validates session still exists before issuing new tokens
func (h *RefreshTokenHandler) Handle(w http.ResponseWriter, r *http.Request) {
	h.logger.Debug("handling token refresh request")

	// Parse and validate request
	dto, err := gatewaydto.ParseRefreshTokenRequest(r)
	if err != nil {
		h.logger.Warn("invalid refresh token request", zap.Error(err))
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

	// Execute token refresh
	response, err := h.refreshTokenService.RefreshToken(r.Context(), &gatewaysvc.RefreshTokenInput{
		RefreshToken: dto.RefreshToken,
	})
	if err != nil {
		h.logger.Warn("token refresh failed", zap.Error(err))

		// Return appropriate error based on error message
		switch err.Error() {
		case "invalid or expired refresh token":
			httperror.ProblemUnauthorized(w, "Invalid or expired refresh token. Please log in again.")
		case "session not found or expired":
			httperror.ProblemUnauthorized(w, "Session has expired or been invalidated. Please log in again.")
		default:
			httperror.ProblemInternalServerError(w, "Failed to refresh token. Please try again later.")
		}
		return
	}

	// CWE-532: Log with safe identifiers only (no PII)
	h.logger.Info("token refresh successful",
		zap.String("user_id", response.UserID),
		zap.String("tenant_id", response.TenantID),
		zap.String("session_id", response.SessionID))

	// Return response with pretty JSON
	httpresponse.OK(w, response)
}
