package site

import (
	"net/http"

	"github.com/gocql/gocql"
	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config/constants"
	sitedto "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/dto/site"
	siteservice "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/site"
	siteusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/site"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httperror"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httpresponse"
)

// RotateAPIKeyHandler handles API key rotation HTTP requests
type RotateAPIKeyHandler struct {
	service siteservice.RotateAPIKeyService
	logger  *zap.Logger
}

// ProvideRotateAPIKeyHandler creates a new RotateAPIKeyHandler
func ProvideRotateAPIKeyHandler(service siteservice.RotateAPIKeyService, logger *zap.Logger) *RotateAPIKeyHandler {
	return &RotateAPIKeyHandler{
		service: service,
		logger:  logger,
	}
}

// Handle handles the HTTP request for rotating a site's API key
// Requires JWT authentication and tenant context
func (h *RotateAPIKeyHandler) Handle(w http.ResponseWriter, r *http.Request) {
	// Get tenant ID from context
	tenantIDStr, ok := r.Context().Value(constants.ContextKeyTenantID).(string)
	if !ok {
		h.logger.Error("tenant ID not found in context")
		httperror.ProblemUnauthorized(w, "Tenant context is required to access this resource.")
		return
	}

	tenantID, err := gocql.ParseUUID(tenantIDStr)
	if err != nil {
		h.logger.Error("invalid tenant ID format", zap.Error(err))
		httperror.ProblemBadRequest(w, "Invalid tenant ID format. Please ensure you have a valid session.")
		return
	}

	// Get site ID from path parameter
	siteIDStr := r.PathValue("id")
	if siteIDStr == "" {
		httperror.ProblemBadRequest(w, "Site ID is required in the request path.")
		return
	}

	// Validate UUID format
	if _, err := gocql.ParseUUID(siteIDStr); err != nil {
		httperror.ProblemBadRequest(w, "Invalid site ID format. Please provide a valid site ID.")
		return
	}

	// Call service
	input := &siteusecase.RotateAPIKeyInput{SiteID: siteIDStr}
	output, err := h.service.RotateAPIKey(r.Context(), tenantID, input)
	if err != nil {
		h.logger.Error("failed to rotate API key",
			zap.Error(err),
			zap.String("site_id", siteIDStr),
			zap.String("tenant_id", tenantID.String()))
		httperror.ProblemNotFound(w, "The requested site could not be found. It may have been deleted or you may not have access to it.")
		return
	}

	// Map to response DTO
	response := sitedto.RotateAPIKeyResponse{
		NewAPIKey:      output.NewAPIKey, // Only shown once!
		OldKeyLastFour: output.OldKeyLastFour,
		RotatedAt:      output.RotatedAt,
	}

	h.logger.Info("API key rotated successfully",
		zap.String("site_id", siteIDStr),
		zap.String("tenant_id", tenantID.String()))

	// Write response
	httpresponse.OK(w, response)
}
