package com.storycove.controller;

import com.storycove.entity.Author;
import com.storycove.entity.Collection;
import com.storycove.entity.Story;
import com.storycove.service.AuthorService;
import com.storycove.service.CollectionService;
import com.storycove.service.SolrService;
import com.storycove.service.SearchServiceAdapter;
import com.storycove.service.StoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * Admin controller for managing Solr operations.
 * Provides endpoints for reindexing and index management.
 */
@RestController
@RequestMapping("/api/admin/search")
public class AdminSearchController {

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

    @Autowired
    private SearchServiceAdapter searchServiceAdapter;

    @Autowired
    private StoryService storyService;

    @Autowired
    private AuthorService authorService;

    @Autowired
    private CollectionService collectionService;

    @Autowired(required = false)
    private SolrService solrService;

    /**
     * Get current search status
     */
    @GetMapping("/status")
    public ResponseEntity<Map<String, Object>> getSearchStatus() {
        try {
            var status = searchServiceAdapter.getSearchStatus();

            return ResponseEntity.ok(Map.of(
                "primaryEngine", status.getPrimaryEngine(),
                "dualWrite", status.isDualWrite(),
                "solrAvailable", status.isSolrAvailable()
            ));
        } catch (Exception e) {
            logger.error("Error getting search status", e);
            return ResponseEntity.internalServerError().body(Map.of(
                "error", "Failed to get search status: " + e.getMessage()
            ));
        }
    }

    /**
     * Reindex all data in Solr
     */
    @PostMapping("/solr/reindex")
    public ResponseEntity<Map<String, Object>> reindexSolr() {
        try {
            logger.info("Starting Solr full reindex");

            if (!searchServiceAdapter.isSearchServiceAvailable()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr is not available or healthy"
                ));
            }

            // Get all data from services
            List<Story> allStories = storyService.findAllWithAssociations();
            List<Author> allAuthors = authorService.findAllWithStories();
            List<Collection> allCollections = collectionService.findAllWithTags();

            // Bulk index directly in Solr
            if (solrService != null) {
                solrService.bulkIndexStories(allStories);
                solrService.bulkIndexAuthors(allAuthors);
                solrService.bulkIndexCollections(allCollections);
            } else {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr service not available"
                ));
            }

            int totalIndexed = allStories.size() + allAuthors.size() + allCollections.size();

            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", String.format("Reindexed %d stories, %d authors and %d collections in Solr",
                    allStories.size(), allAuthors.size(), allCollections.size()),
                "storiesCount", allStories.size(),
                "authorsCount", allAuthors.size(),
                "collectionsCount", allCollections.size(),
                "totalCount", totalIndexed
            ));

        } catch (Exception e) {
            logger.error("Error during Solr reindex", e);
            return ResponseEntity.internalServerError().body(Map.of(
                "success", false,
                "error", "Solr reindex failed: " + e.getMessage()
            ));
        }
    }

    /**
     * Recreate Solr indices
     */
    @PostMapping("/solr/recreate")
    public ResponseEntity<Map<String, Object>> recreateSolrIndices() {
        try {
            logger.info("Starting Solr indices recreation");

            if (!searchServiceAdapter.isSearchServiceAvailable()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr is not available or healthy"
                ));
            }

            // Recreate indices
            if (solrService != null) {
                solrService.recreateIndices();
            } else {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr service not available"
                ));
            }

            // Get all data and reindex
            List<Story> allStories = storyService.findAllWithAssociations();
            List<Author> allAuthors = authorService.findAllWithStories();
            List<Collection> allCollections = collectionService.findAllWithTags();

            // Bulk index after recreation
            solrService.bulkIndexStories(allStories);
            solrService.bulkIndexAuthors(allAuthors);
            solrService.bulkIndexCollections(allCollections);

            int totalIndexed = allStories.size() + allAuthors.size() + allCollections.size();

            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", String.format("Recreated Solr indices and indexed %d stories, %d authors and %d collections",
                    allStories.size(), allAuthors.size(), allCollections.size()),
                "storiesCount", allStories.size(),
                "authorsCount", allAuthors.size(),
                "collectionsCount", allCollections.size(),
                "totalCount", totalIndexed
            ));

        } catch (Exception e) {
            logger.error("Error during Solr indices recreation", e);
            return ResponseEntity.internalServerError().body(Map.of(
                "success", false,
                "error", "Solr indices recreation failed: " + e.getMessage()
            ));
        }
    }

    /**
     * Add libraryId field to Solr schema via Schema API.
     * This is a prerequisite for library-aware indexing.
     */
    @PostMapping("/solr/add-library-field")
    public ResponseEntity<Map<String, Object>> addLibraryField() {
        try {
            logger.info("Starting Solr libraryId field addition");

            if (!searchServiceAdapter.isSearchServiceAvailable()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr is not available or healthy"
                ));
            }

            if (solrService == null) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr service not available"
                ));
            }

            // Add the libraryId field to the schema
            try {
                solrService.addLibraryIdField();
                logger.info("libraryId field added successfully to schema");

                return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message", "libraryId field added successfully to both stories and authors cores",
                    "note", "You can now run the library schema migration"
                ));

            } catch (Exception e) {
                logger.error("Failed to add libraryId field to schema", e);
                return ResponseEntity.internalServerError().body(Map.of(
                    "success", false,
                    "error", "Failed to add libraryId field to schema: " + e.getMessage(),
                    "details", "Check that Solr is accessible and schema is modifiable"
                ));
            }

        } catch (Exception e) {
            logger.error("Error during libraryId field addition", e);
            return ResponseEntity.internalServerError().body(Map.of(
                "success", false,
                "error", "libraryId field addition failed: " + e.getMessage()
            ));
        }
    }

    /**
     * Migrate to library-aware Solr schema.
     * This endpoint handles the migration from non-library-aware to library-aware indexing.
     * It clears existing data and reindexes with library context.
     */
    @PostMapping("/solr/migrate-library-schema")
    public ResponseEntity<Map<String, Object>> migrateLibrarySchema() {
        try {
            logger.info("Starting Solr library schema migration");

            if (!searchServiceAdapter.isSearchServiceAvailable()) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr is not available or healthy"
                ));
            }

            if (solrService == null) {
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Solr service not available"
                ));
            }

            logger.info("Adding libraryId field to Solr schema");

            // First, add the libraryId field to the schema via Schema API
            try {
                solrService.addLibraryIdField();
                logger.info("libraryId field added successfully to schema");
            } catch (Exception e) {
                logger.error("Failed to add libraryId field to schema", e);
                return ResponseEntity.badRequest().body(Map.of(
                    "success", false,
                    "error", "Failed to add libraryId field to schema: " + e.getMessage(),
                    "details", "The schema must support the libraryId field before migration"
                ));
            }

            logger.info("Clearing existing Solr data for library schema migration");

            // Clear existing data that doesn't have libraryId
            try {
                solrService.recreateIndices();
            } catch (Exception e) {
                logger.warn("Could not recreate indices (expected in production): {}", e.getMessage());
                // In production, just clear the data instead
                try {
                    solrService.clearAllDocuments();
                    logger.info("Cleared all documents from Solr cores");
                } catch (Exception clearError) {
                    logger.error("Failed to clear documents", clearError);
                    return ResponseEntity.badRequest().body(Map.of(
                        "success", false,
                        "error", "Failed to clear existing data: " + clearError.getMessage()
                    ));
                }
            }

            // Get all data and reindex with library context
            List<Story> allStories = storyService.findAllWithAssociations();
            List<Author> allAuthors = authorService.findAllWithStories();
            List<Collection> allCollections = collectionService.findAllWithTags();

            logger.info("Reindexing {} stories, {} authors and {} collections with library context",
                allStories.size(), allAuthors.size(), allCollections.size());

            // Bulk index everything (will now include libraryId from current library context)
            solrService.bulkIndexStories(allStories);
            solrService.bulkIndexAuthors(allAuthors);
            solrService.bulkIndexCollections(allCollections);

            int totalIndexed = allStories.size() + allAuthors.size() + allCollections.size();

            logger.info("Solr library schema migration completed successfully");

            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", String.format("Library schema migration completed. Reindexed %d stories, %d authors and %d collections with library context.",
                    allStories.size(), allAuthors.size(), allCollections.size()),
                "storiesCount", allStories.size(),
                "authorsCount", allAuthors.size(),
                "collectionsCount", allCollections.size(),
                "totalCount", totalIndexed,
                "note", "Ensure libraryId field exists in Solr schema before running this migration"
            ));

        } catch (Exception e) {
            logger.error("Error during Solr library schema migration", e);
            return ResponseEntity.internalServerError().body(Map.of(
                "success", false,
                "error", "Library schema migration failed: " + e.getMessage(),
                "details", "Make sure the libraryId field has been added to both stories and authors Solr cores"
            ));
        }
    }
}