package tenant

import (
	"net/http"

	"go.uber.org/zap"

	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/logger"
	"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/validation"
)

// GetHandler handles getting a tenant by ID or slug
type GetHandler struct {
	service tenantservice.GetTenantService
	logger  *zap.Logger
}

// ProvideGetHandler creates a new GetHandler
func ProvideGetHandler(service tenantservice.GetTenantService, logger *zap.Logger) *GetHandler {
	return &GetHandler{
		service: service,
		logger:  logger,
	}
}

// HandleByID handles the HTTP request for getting a tenant by ID
// Security: CWE-20 - Path parameter validation
func (h *GetHandler) HandleByID(w http.ResponseWriter, r *http.Request) {
	// CWE-20: Validate UUID path parameter
	id, err := validation.ValidatePathUUID(r, "id")
	if err != nil {
		h.logger.Warn("invalid tenant ID", zap.Error(err))
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

	// Call service
	input := &tenantusecase.GetTenantInput{ID: id}
	output, err := h.service.GetTenant(r.Context(), input)
	if err != nil {
		// CWE-532: Don't log full error details to prevent information leakage
		h.logger.Debug("failed to get tenant",
			zap.String("tenant_id", id),
			zap.Error(err))
		httperror.ProblemNotFound(w, "The requested tenant could not be found.")
		return
	}

	// CWE-532: Safe logging
	h.logger.Info("tenant retrieved",
		zap.String("tenant_id", output.ID),
		logger.TenantSlugHash(output.Slug))

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

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

// HandleBySlug handles the HTTP request for getting a tenant by slug
// Security: CWE-20 - Path parameter validation
func (h *GetHandler) HandleBySlug(w http.ResponseWriter, r *http.Request) {
	// CWE-20: Validate slug path parameter
	slug, err := validation.ValidatePathSlug(r, "slug")
	if err != nil {
		h.logger.Warn("invalid tenant slug", zap.Error(err))
		httperror.ProblemBadRequest(w, err.Error())
		return
	}

	// Call service
	input := &tenantusecase.GetTenantBySlugInput{Slug: slug}
	output, err := h.service.GetTenantBySlug(r.Context(), input)
	if err != nil {
		// CWE-532: Don't log full error details to prevent information leakage
		h.logger.Debug("failed to get tenant by slug",
			logger.TenantSlugHash(slug),
			zap.Error(err))
		httperror.ProblemNotFound(w, "The requested tenant could not be found.")
		return
	}

	// CWE-532: Safe logging
	h.logger.Info("tenant retrieved by slug",
		zap.String("tenant_id", output.ID),
		logger.TenantSlugHash(output.Slug))

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

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