package user

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

	"go.uber.org/zap"

	userdto "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/dto/user"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/middleware"
	userservice "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/user"
	userusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/user"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httperror"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httpresponse"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/httpvalidation"
)

// CreateHandler handles user creation HTTP requests
type CreateHandler struct {
	service userservice.CreateUserService
	logger  *zap.Logger
}

// ProvideCreateHandler creates a new CreateHandler
func ProvideCreateHandler(service userservice.CreateUserService, logger *zap.Logger) *CreateHandler {
	return &CreateHandler{
		service: service,
		logger:  logger,
	}
}

// Handle handles the HTTP request for creating a user
func (h *CreateHandler) Handle(w http.ResponseWriter, r *http.Request) {
	// Extract tenant from context (set by middleware)
	tenantID, err := middleware.GetTenantID(r.Context())
	if err != nil {
		httperror.ProblemUnauthorized(w, "Tenant context is required to access this resource.")
		return
	}

	// CWE-436: Validate Content-Type before parsing
	if err := httpvalidation.ValidateJSONContentType(r); err != nil {
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

	// Parse request body
	var req userdto.CreateRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		httperror.ProblemBadRequest(w, "Invalid request body format. Please check your JSON syntax.")
		return
	}

	// Map DTO to use case input
	input := &userusecase.CreateUserInput{
		Email:     req.Email,
		FirstName: req.FirstName,
		LastName:  req.LastName,
	}

	// Call service
	output, err := h.service.CreateUser(r.Context(), tenantID, input)
	if err != nil {
		h.logger.Error("failed to create user", zap.Error(err))
		httperror.ProblemInternalServerError(w, "Failed to create user. Please try again later.")
		return
	}

	// Map to response DTO
	response := userdto.CreateResponse{
		ID:        output.ID,
		Email:     output.Email,
		Name:      output.Name,
		CreatedAt: output.CreatedAt,
	}

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