"""Project-wide constants for Local Deep Research."""

from enum import StrEnum
from typing import Dict, List

from .__version__ import __version__

# Honest, identifying User-Agent for APIs that prefer/require identification
# (e.g., academic APIs like arXiv, PubMed, OpenAlex)
USER_AGENT = (
    f"Local-Deep-Research/{__version__} "
    "(Academic Research Tool; https://github.com/LearningCircuit/local-deep-research)"
)

# Browser-like User-Agent for sites that may block bot requests
# Use sparingly and only when necessary
BROWSER_USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/120.0.0.0 Safari/537.36"
)


# --- Research status values ---
# Frontend helpers: src/local_deep_research/web/static/js/config/constants.js
# Injected via:     src/local_deep_research/web/app_factory.py (inject_frontend_constants)
# Template:         src/local_deep_research/web/templates/base.html
# If you add/remove/rename a status here, the frontend picks it up automatically.
class ResearchStatus(StrEnum):
    """Status values for research records.

    Uses StrEnum so values compare equal to plain strings,
    e.g. ``ResearchStatus.COMPLETED == "completed"`` is True.

    Lifecycle::

        [*] ─┬─► QUEUED ─┬─► IN_PROGRESS ─┬─► COMPLETED
             │            │                ├─► FAILED
             │            └─► SUSPENDED    └─► SUSPENDED
             │   (concurrency limit)  (terminated while queued)
             │
             └─► IN_PROGRESS (slots available, skips queue)

    Notes:
        - PENDING is declared as a model default but no creation path
          actually sets it.  All routes use QUEUED or IN_PROGRESS.
        - ERROR is checked as a terminal state but never set by current
          code.  It predates FAILED and exists for backward compatibility
          with older database records.
        - CANCELLED is not used by the research workflow.  It is used by
          the benchmark subsystem (BenchmarkStatus, BenchmarkTaskStatus).
    """

    # --- Active lifecycle states ---
    PENDING = "pending"  # Model default; never set by any creation path
    QUEUED = "queued"  # Waiting for a worker slot
    IN_PROGRESS = "in_progress"  # Worker actively executing

    # --- Terminal states ---
    COMPLETED = "completed"  # Finished successfully
    SUSPENDED = "suspended"  # User terminated the research
    FAILED = "failed"  # Unrecoverable error during execution

    # --- Legacy / compatibility ---
    ERROR = "error"  # Never set; predates FAILED
    CANCELLED = "cancelled"  # Unused by research; for benchmarks


# --- Research library file_path sentinel values ---
FILE_PATH_METADATA_ONLY = "metadata_only"
FILE_PATH_TEXT_ONLY = "text_only_not_stored"
FILE_PATH_BLOB_DELETED = "blob_deleted"
FILE_PATH_SENTINELS = (
    FILE_PATH_METADATA_ONLY,
    FILE_PATH_TEXT_ONLY,
    FILE_PATH_BLOB_DELETED,
)

# --- Snippet / truncation lengths ---
SNIPPET_LENGTH_SHORT = 250
SNIPPET_LENGTH_LONG = 500

# --- Research history collection ---
RESEARCH_HISTORY_COLLECTION_NAME = "History"
RESEARCH_HISTORY_COLLECTION_DESCRIPTION = (
    "Your research history indexed for AI-powered semantic search. "
    "Indexing converts past research reports and their sources into "
    "searchable content, enabling natural-language queries across all "
    "your previous research. Used by the History page search when in "
    "AI or Hybrid mode."
)

# --- Available search strategies (UI-facing) ---
# Single source of truth for strategies shown in all UI dropdowns.
# create_strategy() in search_system_factory.py handles additional names
# (aliases, internal strategies) — this list is purely for the UI.
AVAILABLE_STRATEGIES: List[Dict[str, str]] = [
    {
        "name": "source-based",
        "label": "Source-Based (Best for small <16,000 context window)",
        "description": "Comprehensive research with inline citations. Focuses on finding and extracting information from authoritative sources.",
    },
    {
        "name": "focused-iteration",
        "label": "Focused Iteration - Quick (Minimal text output)",
        "description": "Fast & precise Q&A with iterative search. Good for complex queries requiring specific answers.",
    },
    {
        "name": "focused-iteration-standard",
        "label": "Focused Iteration - Comprehensive (Needs >16,000 context window)",
        "description": "Detailed long-form output with citations. Uses standard citation handler for comprehensive answers.",
    },
    {
        "name": "mcp",
        "label": "MCP ReAct (Agentic research - LLM decides tools)",
        "description": "Agentic research using ReAct pattern. LLM decides what tools to call, analyzes results, and iterates.",
    },
    {
        "name": "langgraph-agent",
        "label": "LangGraph Agent (Autonomous agentic research)",
        "description": "Agentic research where the LLM autonomously decides what to search, which engines to use, and when to synthesize. Supports all search engines as tools.",
    },
]


ALL_STRATEGIES: List[Dict[str, str]] = [
    *AVAILABLE_STRATEGIES,
    {
        "name": "iterative-refinement",
        "label": "Iterative Refinement (Progressive refinement)",
        "description": "LLM-guided progressive refinement. Iteratively refines results using evaluation and follow-up queries.",
    },
    {
        "name": "topic-organization",
        "label": "Topic Organization (Clusters by topic)",
        "description": "Clusters sources into topics with lead texts. Organizes research by themes for structured output.",
    },
    {
        "name": "news_aggregation",
        "label": "News Aggregation (Current events)",
        "description": "Specialized for news aggregation and current events.",
    },
    {
        "name": "rapid",
        "label": "Rapid (Quick single-pass search)",
        "description": "Quick single-pass search for fast results. Good for simple queries.",
    },
    {
        "name": "iterative",
        "label": "Iterative (Loop-based reasoning)",
        "description": "Loop-based reasoning with persistent knowledge accumulation and confidence tracking.",
    },
    {
        "name": "parallel",
        "label": "Parallel (Multiple queries simultaneously)",
        "description": "Runs multiple search queries in parallel for comprehensive coverage.",
    },
    {
        "name": "recursive",
        "label": "Recursive (Query decomposition)",
        "description": "Recursive decomposition of complex queries into simpler sub-queries.",
    },
    {
        "name": "adaptive",
        "label": "Adaptive (Step-by-step reasoning)",
        "description": "Adaptive step-by-step reasoning that adjusts strategy based on results.",
    },
    {
        "name": "smart",
        "label": "Smart (Auto sub-query generation)",
        "description": "Smart decomposition with automatic sub-query generation.",
    },
    {
        "name": "standard",
        "label": "Standard (Basic iterative search)",
        "description": "Basic iterative search strategy for general use.",
    },
    {
        "name": "iterdrag",
        "label": "IterDRAG (Iterative retrieval and generation)",
        "description": "IterDRAG strategy for iterative document retrieval and generation.",
    },
    {
        "name": "iterative-reasoning",
        "label": "Iterative Reasoning (Depth-based exploration)",
        "description": "Iterative reasoning with depth-based exploration.",
    },
    {
        "name": "browsecomp",
        "label": "BrowseComp (Confidence-based iteration)",
        "description": "BrowseComp optimized strategy with confidence-based iteration.",
    },
    {
        "name": "evidence",
        "label": "Evidence (Verification with candidate discovery)",
        "description": "Enhanced evidence-based verification with candidate discovery and pattern learning.",
    },
    {
        "name": "constrained",
        "label": "Constrained (Progressive narrowing)",
        "description": "Progressive constraint-based search that narrows candidates step by step.",
    },
    {
        "name": "parallel-constrained",
        "label": "Parallel Constrained (Combined constraint execution)",
        "description": "Parallel constraint-based search with combined constraint execution.",
    },
    {
        "name": "early-stop-constrained",
        "label": "Early Stop Constrained (With early stopping at 99%)",
        "description": "Parallel constraint search with immediate evaluation and early stopping.",
    },
    {
        "name": "smart-query",
        "label": "Smart Query (LLM query generation)",
        "description": "Smart query generation strategy using LLM-generated queries.",
    },
    {
        "name": "dual-confidence",
        "label": "Dual Confidence (Positive/negative/uncertainty scoring)",
        "description": "Dual confidence scoring with positive/negative/uncertainty.",
    },
    {
        "name": "dual-confidence-with-rejection",
        "label": "Dual Confidence + Rejection (Early rejection)",
        "description": "Dual confidence with early rejection of poor candidates.",
    },
    {
        "name": "concurrent-dual-confidence",
        "label": "Concurrent Dual Confidence (Concurrent search & evaluation)",
        "description": "Concurrent search and evaluation with progressive constraint relaxation.",
    },
    {
        "name": "constraint-parallel",
        "label": "Constraint Parallel (Parallel constraint checking)",
        "description": "Parallel constraint checking with entity seeding and direct property search.",
    },
    {
        "name": "modular",
        "label": "Modular (Modular architecture with constraint checking)",
        "description": "Modular architecture using constraint checking and candidate exploration modules.",
    },
    {
        "name": "modular-parallel",
        "label": "Modular Parallel (Modular with parallel exploration)",
        "description": "Modular strategy with parallel exploration.",
    },
    {
        "name": "browsecomp-entity",
        "label": "BrowseComp Entity (Entity-focused with knowledge graph)",
        "description": "Entity-focused search for BrowseComp questions with knowledge graph building.",
    },
]


def get_available_strategies(show_all: bool = False) -> List[Dict[str, str]]:
    """Get the list of available research strategies.

    Args:
        show_all: If True, return all strategies including advanced/experimental ones.

    Returns:
        List of dictionaries with 'name', 'label', and 'description' keys.
    """
    if show_all:
        return ALL_STRATEGIES.copy()
    return AVAILABLE_STRATEGIES.copy()
