package workers

import (
	"context"
	"strings"
	"time"
	"tm/internal/tender"
	ai_summarizer "tm/pkg/ai_summarizer"
	"tm/pkg/logger"
	"tm/pkg/mongo"
)

// DocumentSummarizationWorker triggers AI summarization for scraped tenders.
// The AI service owns MinIO artefacts; this worker marks Mongo processing flags
// after the pipeline or on-demand summarize API completes.
type DocumentSummarizationWorker struct {
	Mongo      *mongo.ConnectionManager
	Logger     logger.Logger
	TenderRepo tender.TenderRepository
	AIClient   *ai_summarizer.Client
	AIStorage  *ai_summarizer.StorageClient
}

// NewDocumentSummarizationWorker creates a document summarization worker.
func NewDocumentSummarizationWorker(
	mongo *mongo.ConnectionManager,
	logger logger.Logger,
	tenderRepo tender.TenderRepository,
	aiClient *ai_summarizer.Client,
	aiStorage *ai_summarizer.StorageClient,
) *DocumentSummarizationWorker {
	return &DocumentSummarizationWorker{
		Mongo:      mongo,
		Logger:     logger,
		TenderRepo: tenderRepo,
		AIClient:   aiClient,
		AIStorage:  aiStorage,
	}
}

// Run starts the document summarization process.
func (w *DocumentSummarizationWorker) Run() {
	w.Logger.Info("Document summarization worker started", map[string]interface{}{})

	if w.AIClient == nil {
		w.Logger.Warn("AI summarizer client not configured, skipping document summarization run", map[string]interface{}{})
		return
	}

	if refs := w.collectUnSummarizedTenderRefs(context.Background()); len(refs) > 0 {
		if _, err := w.AIClient.TriggerSummarizeBatch(context.Background(), refs); err != nil {
			w.Logger.Warn("Failed to trigger AI summarize batch (continuing with per-tender sync)", map[string]interface{}{
				"tender_count": len(refs),
				"error":        err.Error(),
			})
		}
	}

	limit := 5
	skip := 0
	for {
		tenders, totalCount, err := w.TenderRepo.GetUnSummarizedTenders(context.Background(), limit, skip)
		if err != nil {
			w.Logger.Error("Failed to get un-summarized tenders", map[string]interface{}{
				"error": err.Error(),
			})
			return
		}

		w.Logger.Info("Found tenders for document summarization", map[string]interface{}{
			"count":       len(tenders),
			"total_count": totalCount,
			"skip":        skip,
		})

		if len(tenders) == 0 {
			break
		}

		for i := range tenders {
			t := &tenders[i]
			w.Logger.Info("Processing tender for document summarization", map[string]interface{}{
				"tender_id":             t.ID.Hex(),
				"notice_publication_id": t.NoticePublicationID,
			})
			w.summarizeTender(t)
		}

		skip += len(tenders)
		if int64(skip) >= totalCount {
			break
		}
	}

	w.Logger.Info("Document summarization worker completed", map[string]interface{}{})
}

func (w *DocumentSummarizationWorker) collectUnSummarizedTenderRefs(ctx context.Context) []ai_summarizer.TenderRef {
	limit := 100
	skip := 0
	refs := make([]ai_summarizer.TenderRef, 0)

	for {
		tenders, totalCount, err := w.TenderRepo.GetUnSummarizedTenders(ctx, limit, skip)
		if err != nil {
			w.Logger.Warn("Failed to collect tenders for summarize batch", map[string]interface{}{
				"error": err.Error(),
			})
			return refs
		}
		if len(tenders) == 0 {
			return refs
		}

		for i := range tenders {
			t := &tenders[i]
			if strings.TrimSpace(t.ContractFolderID) == "" || strings.TrimSpace(t.NoticePublicationID) == "" {
				continue
			}
			refs = append(refs, ai_summarizer.NewTenderRef(t.ContractFolderID, t.NoticePublicationID))
		}

		skip += len(tenders)
		if int64(skip) >= totalCount {
			return refs
		}
	}
}

func (w *DocumentSummarizationWorker) summarizeTender(t *tender.Tender) {
	if strings.TrimSpace(t.NoticePublicationID) == "" {
		w.Logger.Warn("Skipping tender summarization: missing notice_publication_id", map[string]interface{}{
			"tender_id": t.ID.Hex(),
		})
		w.markTenderSummarized(t)
		return
	}
	if strings.TrimSpace(t.ContractFolderID) == "" {
		w.Logger.Warn("Skipping tender summarization: missing contract_folder_id", map[string]interface{}{
			"tender_id": t.ID.Hex(),
		})
		w.markTenderSummarized(t)
		return
	}

	ctx := context.Background()
	if w.isSummaryReadyInStorage(ctx, t) {
		w.markTenderSummarized(t)
		return
	}

	req := ai_summarizer.NewSummarizeRequest(t.ContractFolderID, t.NoticePublicationID)
	if _, err := w.AIClient.FetchSummaryOnDemand(ctx, req); err != nil {
		w.Logger.Error("Failed to summarize tender via AI service", map[string]interface{}{
			"tender_id":             t.ID.Hex(),
			"notice_publication_id": t.NoticePublicationID,
			"contract_folder_id":    t.ContractFolderID,
			"error":                 err.Error(),
		})
		return
	}

	if !w.isSummaryReadyInStorage(ctx, t) {
		w.Logger.Warn("AI summarize completed but storage is not ready yet", map[string]interface{}{
			"tender_id":             t.ID.Hex(),
			"notice_publication_id": t.NoticePublicationID,
		})
	}

	w.markTenderSummarized(t)
}

func (w *DocumentSummarizationWorker) isSummaryReadyInStorage(ctx context.Context, t *tender.Tender) bool {
	if w.AIStorage == nil {
		return false
	}
	ready, err := w.AIStorage.IsSummaryReady(ctx, t.ContractFolderID, t.NoticePublicationID)
	if err != nil {
		w.Logger.Debug("Could not check summarization status in storage", map[string]interface{}{
			"tender_id":             t.ID.Hex(),
			"notice_publication_id": t.NoticePublicationID,
			"error":                 err.Error(),
		})
		return false
	}
	return ready
}

func (w *DocumentSummarizationWorker) markTenderSummarized(t *tender.Tender) {
	now := time.Now().Unix()
	t.ProcessingMetadata.DocumentsSummarized = true
	t.ProcessingMetadata.DocumentsSummarizedAt = now
	t.UpdatedAt = now

	if err := w.TenderRepo.Update(context.Background(), t); err != nil {
		w.Logger.Error("Failed to update tender summarization status", map[string]interface{}{
			"tender_id":             t.ID.Hex(),
			"notice_publication_id": t.NoticePublicationID,
			"error":                 err.Error(),
		})
		return
	}

	w.Logger.Info("Tender marked as summarized", map[string]interface{}{
		"tender_id":             t.ID.Hex(),
		"notice_publication_id": t.NoticePublicationID,
	})
}
