# citation_handler.py

from typing import Any, Dict, List, Optional, Union

from loguru import logger

from .utilities.type_utils import unwrap_setting


class CitationHandler:
    """
    Configurable citation handler that delegates to specific implementations.
    Maintains backward compatibility while allowing strategy-specific handlers.
    """

    def __init__(
        self, llm, handler_type: Optional[str] = None, settings_snapshot=None
    ):
        self.llm = llm
        self.settings_snapshot = settings_snapshot or {}

        # Determine which handler to use
        if handler_type is None:
            # Try to get from settings snapshot, default to standard
            if "citation.handler_type" in self.settings_snapshot:
                value = self.settings_snapshot["citation.handler_type"]
                handler_type = unwrap_setting(value)
            else:
                handler_type = "standard"

        # Import and instantiate the appropriate handler
        self._handler = self._create_handler(handler_type)

        # For backward compatibility, expose internal methods
        self._create_documents = self._handler._create_documents
        self._format_sources = self._handler._format_sources

    def _create_handler(self, handler_type: str):
        """Create the appropriate citation handler based on type."""
        handler_type = handler_type.lower()

        if handler_type == "standard":
            from .citation_handlers.standard_citation_handler import (
                StandardCitationHandler,
            )

            logger.info("Using StandardCitationHandler")
            return StandardCitationHandler(
                self.llm, settings_snapshot=self.settings_snapshot
            )

        if handler_type in ["forced", "forced_answer", "browsecomp"]:
            from .citation_handlers.forced_answer_citation_handler import (
                ForcedAnswerCitationHandler,
            )

            logger.info(
                "Using ForcedAnswerCitationHandler for better benchmark performance"
            )
            return ForcedAnswerCitationHandler(
                self.llm, settings_snapshot=self.settings_snapshot
            )

        if handler_type in ["precision", "precision_extraction", "simpleqa"]:
            from .citation_handlers.precision_extraction_handler import (
                PrecisionExtractionHandler,
            )

            logger.info(
                "Using PrecisionExtractionHandler for precise answer extraction"
            )
            return PrecisionExtractionHandler(
                self.llm, settings_snapshot=self.settings_snapshot
            )

        logger.warning(
            f"Unknown citation handler type: {handler_type}, falling back to standard"
        )
        from .citation_handlers.standard_citation_handler import (
            StandardCitationHandler,
        )

        return StandardCitationHandler(
            self.llm, settings_snapshot=self.settings_snapshot
        )

    def set_stream_callback(self, callback):
        """Set a streaming callback on the underlying handler."""
        if hasattr(self._handler, "set_stream_callback"):
            self._handler.set_stream_callback(callback)

    def analyze_initial(
        self, query: str, search_results: Union[str, List[Dict]]
    ) -> Dict[str, Any]:
        """Delegate to the configured handler."""
        return self._handler.analyze_initial(query, search_results)  # type: ignore[no-any-return]

    def analyze_followup(
        self,
        question: str,
        search_results: Union[str, List[Dict]],
        previous_knowledge: str,
        nr_of_links: int,
    ) -> Dict[str, Any]:
        """Delegate to the configured handler."""
        return self._handler.analyze_followup(  # type: ignore[no-any-return]
            question, search_results, previous_knowledge, nr_of_links
        )
