package page

import (
	"context"

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

	pageusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/page"
)

// SearchPagesService handles page search operations
type SearchPagesService interface {
	SearchPages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.SearchPagesInput) (*pageusecase.SearchPagesOutput, error)
}

type searchPagesService struct {
	// Focused usecases
	validateSiteUC   *pageusecase.ValidateSiteForSearchUseCase
	executeSearchUC  *pageusecase.ExecuteSearchQueryUseCase
	incrementCountUC *pageusecase.IncrementSearchCountUseCase

	logger *zap.Logger
}

// NewSearchPagesService creates a new SearchPagesService
func NewSearchPagesService(
	validateSiteUC *pageusecase.ValidateSiteForSearchUseCase,
	executeSearchUC *pageusecase.ExecuteSearchQueryUseCase,
	incrementCountUC *pageusecase.IncrementSearchCountUseCase,
	logger *zap.Logger,
) SearchPagesService {
	return &searchPagesService{
		validateSiteUC:   validateSiteUC,
		executeSearchUC:  executeSearchUC,
		incrementCountUC: incrementCountUC,
		logger:           logger.Named("search-pages-service"),
	}
}

// SearchPages orchestrates the page search workflow
func (s *searchPagesService) SearchPages(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.SearchPagesInput) (*pageusecase.SearchPagesOutput, error) {
	s.logger.Info("searching pages",
		zap.String("tenant_id", tenantID.String()),
		zap.String("site_id", siteID.String()),
		zap.String("query", input.Query))

	// Step 1: Validate site (no quota check - usage-based billing)
	site, err := s.validateSiteUC.Execute(ctx, tenantID, siteID)
	if err != nil {
		s.logger.Error("failed to validate site", zap.Error(err))
		return nil, err
	}

	// Step 2: Execute search query
	result, err := s.executeSearchUC.Execute(ctx, siteID, input.Query, input.Limit, input.Offset, input.Filter)
	if err != nil {
		s.logger.Error("failed to execute search", zap.Error(err))
		return nil, err
	}

	// Step 3: Increment search count (for billing tracking)
	if err := s.incrementCountUC.Execute(ctx, site); err != nil {
		s.logger.Warn("failed to increment search count (non-fatal)", zap.Error(err))
		// Don't fail the search operation
	}

	s.logger.Info("pages searched successfully",
		zap.String("site_id", siteID.String()),
		zap.Int64("total_hits", result.TotalHits))

	return &pageusecase.SearchPagesOutput{
		Hits:             result.Hits,
		Query:            result.Query,
		ProcessingTimeMs: result.ProcessingTimeMs,
		TotalHits:        result.TotalHits,
		Limit:            result.Limit,
		Offset:           result.Offset,
	}, nil
}
