"""
Service layer for follow-up research functionality.

This service handles the business logic for follow-up research,
including loading parent research context and orchestrating the search.
"""

from typing import Dict, Any
from loguru import logger

from ..database.models import ResearchHistory
from ..database.session_context import get_user_db_session
from ..web.services.research_sources_service import ResearchSourcesService
from .models import FollowUpRequest


class FollowUpResearchService:
    """Service for handling follow-up research operations."""

    def __init__(self, username: str | None = None):
        """
        Initialize the follow-up research service.

        Args:
            username: Username for database access
        """
        self.username = username

    def load_parent_research(self, parent_research_id: str) -> Dict[str, Any]:
        """
        Load parent research data from the database.

        Args:
            parent_research_id: ID of the parent research

        Returns:
            Dictionary containing parent research data including:
            - report_content: The generated report
            - resources: List of research resources/links
            - query: Original research query
            - strategy: Strategy used
        """
        try:
            with get_user_db_session(self.username) as session:
                # Load research history
                research = (
                    session.query(ResearchHistory)
                    .filter_by(id=parent_research_id)
                    .first()
                )

                if not research:
                    logger.warning(
                        f"Parent research not found: {parent_research_id}"
                    )
                    return {}

                logger.info(
                    f"Found research: {research.id}, has meta: {research.research_meta is not None}"
                )

                # Use the ResearchSourcesService to get sources properly from database
                sources_service = ResearchSourcesService()
                resource_list = sources_service.get_research_sources(
                    parent_research_id, username=self.username
                )

                logger.info(
                    f"Found {len(resource_list)} sources from ResearchResource table"
                )

                # If no sources in database, try to get from research_meta as fallback
                if not resource_list and research.research_meta:
                    logger.info(
                        "No sources in database, checking research_meta"
                    )
                    logger.info(
                        f"Research meta keys: {list(research.research_meta.keys()) if isinstance(research.research_meta, dict) else 'Not a dict'}"
                    )

                    # Try different possible locations for sources in research_meta
                    meta_sources = (
                        research.research_meta.get("all_links_of_system", [])
                        or research.research_meta.get("sources", [])
                        or research.research_meta.get("links", [])
                        or []
                    )

                    if meta_sources:
                        logger.info(
                            f"Found {len(meta_sources)} sources in research_meta, saving to database"
                        )
                        # Source migration is non-fatal: the followup can
                        # still proceed using meta_sources directly even if
                        # saving to the ResearchResource table fails (e.g.
                        # encrypted DB password expired mid-session).
                        try:
                            saved = sources_service.save_research_sources(
                                parent_research_id,
                                meta_sources,
                                username=self.username,
                            )
                            logger.info(f"Saved {saved} sources to database")

                            # Now retrieve them properly formatted
                            resource_list = (
                                sources_service.get_research_sources(
                                    parent_research_id,
                                    username=self.username,
                                )
                            )
                        except Exception:
                            logger.exception(
                                f"Failed to save/retrieve sources for parent research "
                                f"{parent_research_id} (continuing with raw meta_sources)"
                            )

                # Convert to dictionary format
                parent_data = {
                    "research_id": research.id,
                    "query": research.query,
                    "report_content": research.report_content,
                    "formatted_findings": research.research_meta.get(
                        "formatted_findings", ""
                    )
                    if research.research_meta
                    else "",
                    "strategy": research.research_meta.get("strategy_name", "")
                    if research.research_meta
                    else "",
                    "resources": resource_list,
                    "all_links_of_system": resource_list,
                }

                logger.info(
                    f"Loaded parent research {parent_research_id} with "
                    f"{len(resource_list)} sources"
                )

                return parent_data

        except Exception:
            logger.exception("Error loading parent research")
            return {}

    def prepare_research_context(
        self, parent_research_id: str
    ) -> Dict[str, Any]:
        """
        Prepare the research context for the contextual follow-up strategy.

        Args:
            parent_research_id: ID of the parent research

        Returns:
            Research context dictionary for the strategy
        """
        parent_data = self.load_parent_research(parent_research_id)

        if not parent_data:
            logger.warning("No parent data found, returning empty context")
            return {}

        # Format context for the strategy
        return {
            "parent_research_id": parent_research_id,
            "past_links": parent_data.get("all_links_of_system", []),
            "past_findings": parent_data.get("formatted_findings", ""),
            "report_content": parent_data.get("report_content", ""),
            "resources": parent_data.get("resources", []),
            "all_links_of_system": parent_data.get("all_links_of_system", []),
            "original_query": parent_data.get("query", ""),
        }

    def perform_followup(self, request: FollowUpRequest) -> Dict[str, Any]:
        """
        Perform a follow-up research based on parent research.

        This method prepares the context and parameters for the research system
        to use the contextual follow-up strategy.

        Args:
            request: FollowUpRequest with question and parent research ID

        Returns:
            Dictionary with research parameters for the research system
        """
        # Prepare the research context from parent
        research_context = self.prepare_research_context(
            request.parent_research_id
        )

        if not research_context:
            logger.warning(
                f"Parent research not found: {request.parent_research_id}, using empty context"
            )
            # Use empty context to allow follow-up without parent
            research_context = {
                "parent_research_id": request.parent_research_id,
                "past_links": [],
                "past_findings": "",
                "report_content": "",
                "resources": [],
                "all_links_of_system": [],
                "original_query": "",
            }

        # Prepare parameters for the research system
        research_params = {
            "query": request.question,
            "strategy": "contextual-followup",
            "delegate_strategy": request.strategy,
            "max_iterations": request.max_iterations,
            "questions_per_iteration": request.questions_per_iteration,
            "research_context": research_context,
            "parent_research_id": request.parent_research_id,
        }

        logger.info(
            f"Prepared follow-up research for question: '{request.question}' "
            f"based on parent: {request.parent_research_id}"
        )

        return research_params
