// cloud/maplefile-backend/internal/maplefile/interface/http/dashboard/get.go
package dashboard

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

	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/interface/http/middleware"
	svc_dashboard "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/service/dashboard"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror"
)

type GetDashboardHTTPHandler struct {
	config     *config.Configuration
	logger     *zap.Logger
	service    svc_dashboard.GetDashboardService
	middleware middleware.Middleware
}

func NewGetDashboardHTTPHandler(
	config *config.Configuration,
	logger *zap.Logger,
	service svc_dashboard.GetDashboardService,
	middleware middleware.Middleware,
) *GetDashboardHTTPHandler {
	logger = logger.With(zap.String("module", "maplefile"))
	logger = logger.Named("GetDashboardHTTPHandler")
	return &GetDashboardHTTPHandler{
		config:     config,
		logger:     logger,
		service:    service,
		middleware: middleware,
	}
}

func (*GetDashboardHTTPHandler) Pattern() string {
	return "GET /api/v1/dashboard"
}

func (h *GetDashboardHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// Apply middleware before handling the request
	h.middleware.Attach(h.Execute)(w, req)
}

func (h *GetDashboardHTTPHandler) Execute(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	//
	// STEP 1: Execute service
	//
	resp, err := h.service.Execute(ctx)
	if err != nil {
		h.logger.Error("Failed to get dashboard data",
			zap.Error(err))
		// Service returns RFC 9457 errors, use RespondWithError to handle them
		httperror.RespondWithError(w, r, err)
		return
	}

	//
	// STEP 2: Encode and return response
	//
	if resp == nil {
		h.logger.Error("No dashboard data returned from service")
		problem := httperror.NewInternalServerError("Failed to retrieve dashboard data. Please try again.").
			WithInstance(r.URL.Path).
			WithTraceID(httperror.ExtractRequestID(r))
		httperror.RespondWithProblem(w, problem)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(resp); err != nil {
		h.logger.Error("Failed to encode dashboard response",
			zap.Error(err))
		// At this point headers are already sent, log the error but can't send RFC 9457 response
		return
	}

	h.logger.Debug("Dashboard data successfully returned")
}
