package page

import (
	"context"

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

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

// SyncStatusService handles sync status operations
type SyncStatusService interface {
	GetSyncStatus(ctx context.Context, tenantID, siteID gocql.UUID) (*pageusecase.SyncStatusOutput, error)
	GetPageDetails(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.GetPageDetailsInput) (*pageusecase.PageDetailsOutput, error)
}

type syncStatusService struct {
	// Focused usecases
	validateSiteUC   *pageusecase.ValidateSiteForStatusUseCase
	getStatsUC       *pageusecase.GetPageStatisticsUseCase
	getIndexStatusUC *pageusecase.GetSearchIndexStatusUseCase
	getPageByIDUC    *pageusecase.GetPageByIDUseCase

	logger *zap.Logger
}

// NewSyncStatusService creates a new SyncStatusService
func NewSyncStatusService(
	validateSiteUC *pageusecase.ValidateSiteForStatusUseCase,
	getStatsUC *pageusecase.GetPageStatisticsUseCase,
	getIndexStatusUC *pageusecase.GetSearchIndexStatusUseCase,
	getPageByIDUC *pageusecase.GetPageByIDUseCase,
	logger *zap.Logger,
) SyncStatusService {
	return &syncStatusService{
		validateSiteUC:   validateSiteUC,
		getStatsUC:       getStatsUC,
		getIndexStatusUC: getIndexStatusUC,
		getPageByIDUC:    getPageByIDUC,
		logger:           logger.Named("sync-status-service"),
	}
}

// GetSyncStatus orchestrates retrieving sync status for a site
func (s *syncStatusService) GetSyncStatus(ctx context.Context, tenantID, siteID gocql.UUID) (*pageusecase.SyncStatusOutput, error) {
	s.logger.Info("getting sync status",
		zap.String("tenant_id", tenantID.String()),
		zap.String("site_id", siteID.String()))

	// Step 1: Validate site
	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: Get page statistics
	stats, err := s.getStatsUC.Execute(ctx, siteID)
	if err != nil {
		s.logger.Error("failed to get page statistics", zap.Error(err))
		return nil, err
	}

	// Step 3: Get search index status
	indexStatus, err := s.getIndexStatusUC.Execute(ctx, siteID)
	if err != nil {
		s.logger.Error("failed to get search index status", zap.Error(err))
		return nil, err
	}

	s.logger.Info("sync status retrieved successfully",
		zap.String("site_id", siteID.String()),
		zap.Int64("total_pages", stats.TotalPages))

	// Step 4: Build output
	return &pageusecase.SyncStatusOutput{
		SiteID:              siteID.String(),
		TotalPages:          stats.TotalPages,
		PublishedPages:      stats.PublishedPages,
		DraftPages:          stats.DraftPages,
		LastSyncedAt:        site.LastIndexedAt,
		PagesIndexedMonth:   site.MonthlyPagesIndexed,
		SearchRequestsMonth: site.SearchRequestsCount,
		LastResetAt:         site.LastResetAt,
		SearchIndexStatus:   indexStatus.Status,
		SearchIndexDocCount: indexStatus.DocumentCount,
	}, nil
}

// GetPageDetails orchestrates retrieving details for a specific page
func (s *syncStatusService) GetPageDetails(ctx context.Context, tenantID, siteID gocql.UUID, input *pageusecase.GetPageDetailsInput) (*pageusecase.PageDetailsOutput, error) {
	s.logger.Info("getting page details",
		zap.String("tenant_id", tenantID.String()),
		zap.String("site_id", siteID.String()),
		zap.String("page_id", input.PageID))

	// Step 1: Validate 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: Get page by ID
	page, err := s.getPageByIDUC.Execute(ctx, siteID, input.PageID)
	if err != nil {
		s.logger.Error("failed to get page", zap.Error(err))
		return nil, err
	}

	s.logger.Info("page details retrieved successfully",
		zap.String("site_id", siteID.String()),
		zap.String("page_id", input.PageID))

	// Step 3: Build output
	isIndexed := !page.IndexedAt.IsZero()

	return &pageusecase.PageDetailsOutput{
		PageID:           page.PageID,
		Title:            page.Title,
		Excerpt:          page.Excerpt,
		URL:              page.URL,
		Status:           page.Status,
		PostType:         page.PostType,
		Author:           page.Author,
		PublishedAt:      page.PublishedAt,
		ModifiedAt:       page.ModifiedAt,
		IndexedAt:        page.IndexedAt,
		MeilisearchDocID: page.MeilisearchDocID,
		IsIndexed:        isIndexed,
	}, nil
}
