// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/interface/http/tag/list_files_by_tag.go
package tag

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

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

	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/tag"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror"
)

type ListFilesByTagHandler struct {
	UseCase *tag.ListFilesByTagUseCase
	Logger  *zap.Logger
}

func NewListFilesByTagHandler(
	useCase *tag.ListFilesByTagUseCase,
	logger *zap.Logger,
) *ListFilesByTagHandler {
	return &ListFilesByTagHandler{
		UseCase: useCase,
		Logger:  logger,
	}
}

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

	// Extract user ID from context (set by auth middleware)
	userID, ok := ctx.Value("user_id").(gocql.UUID)
	if !ok {
		httperror.ResponseError(w, httperror.NewUnauthorizedError("user not authenticated"))
		return
	}

	// Get tags parameter (required, comma-separated UUIDs)
	tagsParam := r.URL.Query().Get("tags")
	if tagsParam == "" {
		httperror.ResponseError(w, httperror.NewBadRequestError("tags parameter is required"))
		return
	}

	// Parse comma-separated tag IDs
	tagIDStrs := strings.Split(tagsParam, ",")
	if len(tagIDStrs) == 0 {
		httperror.ResponseError(w, httperror.NewBadRequestError("at least one tag ID is required"))
		return
	}

	tagIDs := make([]gocql.UUID, 0, len(tagIDStrs))
	for _, idStr := range tagIDStrs {
		id, err := gocql.ParseUUID(strings.TrimSpace(idStr))
		if err != nil {
			httperror.ResponseError(w, httperror.NewBadRequestError("invalid tag ID: "+idStr))
			return
		}
		tagIDs = append(tagIDs, id)
	}

	// Parse pagination parameters
	limitStr := r.URL.Query().Get("limit")
	limit := 50 // default
	if limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 {
			limit = parsedLimit
		}
	}

	cursor := r.URL.Query().Get("cursor")

	// Execute multi-tag use case
	files, nextCursor, err := h.UseCase.Execute(ctx, userID, tagIDs, limit, cursor)
	if err != nil {
		h.Logger.Error("failed to list files by tags",
			zap.Int("tag_count", len(tagIDs)),
			zap.Error(err))
		httperror.ResponseError(w, httperror.NewInternalServerError("failed to list files"))
		return
	}

	// Build response
	response := map[string]interface{}{
		"files":     files,
		"cursor":    nextCursor,
		"has_more":  nextCursor != "",
		"tag_count": len(tagIDs),
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(response)
}
