package tenant

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

	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config/constants"
	tenantdto "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/dto/tenant"
	tenantservice "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/tenant"
	tenantusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/tenant"
	"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"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/logger"
)

// CreateHandler handles tenant creation HTTP requests
type CreateHandler struct {
	service tenantservice.CreateTenantService
	logger  *zap.Logger
}

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

// Handle handles the HTTP request for creating a tenant
// Note: This endpoint does NOT require tenant middleware since we're creating a tenant
// Security: CWE-20, CWE-79, CWE-117 - Comprehensive input validation and sanitization
func (h *CreateHandler) Handle(w http.ResponseWriter, r *http.Request) {
	// CWE-436: Enforce strict Content-Type validation
	if err := httpvalidation.ValidateJSONContentTypeStrict(r); err != nil {
		h.logger.Warn("invalid content type", zap.String("content_type", r.Header.Get("Content-Type")))
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

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

	// CWE-20: Comprehensive input validation
	if err := req.Validate(); err != nil {
		h.logger.Warn("tenant creation validation failed", zap.Error(err))
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

	// Extract user context for logging
	userID := "unknown"
	if uid := r.Context().Value(constants.SessionUserID); uid != nil {
		if userIDUint, ok := uid.(uint64); ok {
			userID = fmt.Sprintf("%d", userIDUint)
		}
	}

	// CWE-532: Safe logging with hashed PII
	h.logger.Info("creating tenant",
		zap.String("user_id", userID),
		logger.TenantSlugHash(req.Slug))

	// Map DTO to use case input
	input := &tenantusecase.CreateTenantInput{
		Name: req.Name,
		Slug: req.Slug,
	}

	// Call service
	output, err := h.service.CreateTenant(r.Context(), input)
	if err != nil {
		// CWE-532: Log with safe identifiers
		h.logger.Error("failed to create tenant",
			zap.Error(err),
			zap.String("user_id", userID),
			logger.TenantSlugHash(req.Slug))
		httperror.ProblemInternalServerError(w, "Failed to create tenant. Please try again later.")
		return
	}

	// CWE-532: Log successful creation
	h.logger.Info("tenant created successfully",
		zap.String("user_id", userID),
		zap.String("tenant_id", output.ID),
		logger.TenantSlugHash(output.Slug))

	// Map to response DTO
	response := tenantdto.CreateResponse{
		ID:        output.ID,
		Name:      output.Name,
		Slug:      output.Slug,
		Status:    output.Status,
		CreatedAt: output.CreatedAt,
	}

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