package com.storycove.service;

import com.storycove.entity.Author;
import com.storycove.entity.Collection;
import com.storycove.entity.Story;
import com.storycove.repository.AuthorRepository;
import com.storycove.repository.CollectionRepository;
import com.storycove.repository.StoryRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * Performs a nightly complete reindex of all entities (stories, authors, collections)
 * to keep the Solr search index in sync with the database.
 *
 * This scheduler runs at 3 AM by default (configurable via storycove.search.nightly-reindex-cron).
 * It is intentionally skipped when no library is authenticated so that it never indexes documents
 * with the fallback libraryId="default", which would make them invisible to searches.
 */
@Component
@ConditionalOnProperty(name = "storycove.search.enabled", havingValue = "true", matchIfMissing = true)
public class NightlyReindexScheduler {

    private static final Logger logger = LoggerFactory.getLogger(NightlyReindexScheduler.class);

    private final StoryRepository storyRepository;
    private final AuthorRepository authorRepository;
    private final CollectionRepository collectionRepository;
    private final SearchServiceAdapter searchServiceAdapter;
    private final LibraryService libraryService;

    @Autowired
    public NightlyReindexScheduler(StoryRepository storyRepository,
                                   AuthorRepository authorRepository,
                                   CollectionRepository collectionRepository,
                                   SearchServiceAdapter searchServiceAdapter,
                                   LibraryService libraryService) {
        this.storyRepository = storyRepository;
        this.authorRepository = authorRepository;
        this.collectionRepository = collectionRepository;
        this.searchServiceAdapter = searchServiceAdapter;
        this.libraryService = libraryService;
    }

    @Scheduled(cron = "${storycove.search.nightly-reindex-cron:0 0 3 * * ?}") // 3 AM daily by default
    public void reindexAll() {
        logger.info("========================================");
        logger.info("Starting nightly full search reindexing...");
        logger.info("========================================");

        if (!searchServiceAdapter.isSearchServiceAvailable()) {
            logger.warn("Solr is not available — skipping nightly reindexing.");
            return;
        }

        // Only reindex when a library is active so every document gets the correct libraryId.
        // Without this guard, documents would be indexed with libraryId="default" and become
        // invisible to searches that filter by the real library ID.
        if (libraryService.getCurrentLibraryId() == null) {
            logger.warn("No active library — skipping nightly reindexing.");
            logger.warn("A user must authenticate before the nightly reindex can run.");
            return;
        }

        long startTime = System.currentTimeMillis();
        int storiesIndexed = 0;
        int authorsIndexed = 0;
        int collectionsIndexed = 0;

        try {
            List<Story> stories = storyRepository.findAllWithAssociations();
            if (!stories.isEmpty()) {
                searchServiceAdapter.bulkIndexStories(stories);
                storiesIndexed = stories.size();
                logger.info("Reindexed {} stories", storiesIndexed);
            }
        } catch (Exception e) {
            logger.error("Failed to reindex stories during nightly run", e);
        }

        try {
            List<Author> authors = authorRepository.findAll();
            if (!authors.isEmpty()) {
                searchServiceAdapter.bulkIndexAuthors(authors);
                authorsIndexed = authors.size();
                logger.info("Reindexed {} authors", authorsIndexed);
            }
        } catch (Exception e) {
            logger.error("Failed to reindex authors during nightly run", e);
        }

        try {
            List<Collection> collections = collectionRepository.findAllWithTags();
            if (!collections.isEmpty()) {
                searchServiceAdapter.bulkIndexCollections(collections);
                collectionsIndexed = collections.size();
                logger.info("Reindexed {} collections", collectionsIndexed);
            }
        } catch (Exception e) {
            logger.error("Failed to reindex collections during nightly run", e);
        }

        long duration = System.currentTimeMillis() - startTime;
        logger.info("========================================");
        logger.info("Nightly reindexing completed in {}ms — {} stories, {} authors, {} collections",
            duration, storiesIndexed, authorsIndexed, collectionsIndexed);
        logger.info("========================================");
    }
}
