"""
REST API for Local Deep Research.
Provides HTTP access to programmatic search and research capabilities.
"""

import logging
import time
from functools import wraps

from flask import Blueprint, jsonify, request

from ..api.research_functions import analyze_documents
from .services.settings_service import get_setting

# Create a blueprint for the API
api_blueprint = Blueprint("api_v1", __name__, url_prefix="/api/v1")
logger = logging.getLogger(__name__)

# Rate limiting data store: {ip_address: [timestamp1, timestamp2, ...]}
rate_limit_data = {}


def api_access_control(f):
    """
    Decorator to enforce API access control:
    - Check if API is enabled
    - Enforce rate limiting
    """

    @wraps(f)
    def decorated_function(*args, **kwargs):
        # Check if API is enabled
        api_enabled = get_setting("app.enable_api", True)  # Default to enabled
        if not api_enabled:
            return jsonify({"error": "API access is disabled"}), 403

        # Implement rate limiting
        rate_limit = get_setting(
            "app.api_rate_limit", 60
        )  # Default 60 requests per minute
        if rate_limit:
            client_ip = request.remote_addr
            current_time = time.time()

            # Initialize or clean up old requests for this IP
            if client_ip not in rate_limit_data:
                rate_limit_data[client_ip] = []

            # Remove timestamps older than 1 minute
            rate_limit_data[client_ip] = [
                ts
                for ts in rate_limit_data[client_ip]
                if current_time - ts < 60
            ]

            # Check if rate limit is exceeded
            if len(rate_limit_data[client_ip]) >= rate_limit:
                return (
                    jsonify(
                        {
                            "error": f"Rate limit exceeded. Maximum {rate_limit} requests per minute allowed."
                        }
                    ),
                    429,
                )

            # Add current timestamp to the list
            rate_limit_data[client_ip].append(current_time)

        return f(*args, **kwargs)

    return decorated_function


@api_blueprint.route("/", methods=["GET"])
@api_access_control
def api_documentation():
    """
    Provide documentation on the available API endpoints.
    """
    api_docs = {
        "api_version": "v1",
        "description": "REST API for Local Deep Research",
        "endpoints": [
            {
                "path": "/api/v1/quick_summary",
                "method": "POST",
                "description": "Generate a quick research summary",
                "parameters": {
                    "query": "Research query (required)",
                    "search_tool": "Search engine to use (optional)",
                    "iterations": "Number of search iterations (optional)",
                    "temperature": "LLM temperature (optional)",
                },
            },
            {
                "path": "/api/v1/generate_report",
                "method": "POST",
                "description": "Generate a comprehensive research report",
                "parameters": {
                    "query": "Research query (required)",
                    "output_file": "Path to save report (optional)",
                    "searches_per_section": "Searches per report section (optional)",
                    "model_name": "LLM model to use (optional)",
                    "temperature": "LLM temperature (optional)",
                },
            },
            {
                "path": "/api/v1/analyze_documents",
                "method": "POST",
                "description": "Search and analyze documents in a local collection",
                "parameters": {
                    "query": "Search query (required)",
                    "collection_name": "Local collection name (required)",
                    "max_results": "Maximum results to return (optional)",
                    "temperature": "LLM temperature (optional)",
                    "force_reindex": "Force collection reindexing (optional)",
                },
            },
        ],
    }

    return jsonify(api_docs)


@api_blueprint.route("/health", methods=["GET"])
def health_check():
    """Simple health check endpoint."""
    return jsonify(
        {"status": "ok", "message": "API is running", "timestamp": time.time()}
    )


@api_blueprint.route("/quick_summary_test", methods=["POST"])
@api_access_control
def api_quick_summary_test():
    """Test endpoint using programmatic access with minimal parameters for fast testing."""
    data = request.json
    if not data or "query" not in data:
        return jsonify({"error": "Query parameter is required"}), 400

    query = data.get("query")

    try:
        # Import here to avoid circular imports
        from ..api.research_functions import quick_summary

        logger.info(f"Processing quick_summary_test request: query='{query}'")

        # Use minimal parameters for faster testing
        result = quick_summary(
            query=query,
            search_tool="wikipedia",  # Use fast Wikipedia search for testing
            iterations=1,  # Single iteration for speed
            temperature=0.7,
        )

        return jsonify(result)
    except Exception as e:
        logger.error(
            f"Error in quick_summary_test API: {str(e)}", exc_info=True
        )
        return (
            jsonify(
                {
                    "error": "An internal error has occurred. Please try again later."
                }
            ),
            500,
        )


@api_blueprint.route("/quick_summary", methods=["POST"])
@api_access_control
def api_quick_summary():
    """
    Generate a quick research summary via REST API.

    POST /api/v1/quick_summary
    {
        "query": "Advances in fusion energy research",
        "search_tool": "auto",  # Optional: search engine to use
        "iterations": 2,        # Optional: number of search iterations
        "temperature": 0.7      # Optional: LLM temperature
    }
    """
    data = request.json
    if not data or "query" not in data:
        return jsonify({"error": "Query parameter is required"}), 400

    # Extract query and optional parameters
    query = data.get("query")
    params = {k: v for k, v in data.items() if k != "query"}

    try:
        # Import here to avoid circular imports
        from ..api.research_functions import quick_summary

        logger.info(f"Processing quick_summary request: query='{query}'")

        # Set reasonable defaults for API use
        params.setdefault("temperature", 0.7)
        params.setdefault("search_tool", "auto")
        params.setdefault("iterations", 1)

        # Call the actual research function
        result = quick_summary(query, **params)

        return jsonify(result)
    except TimeoutError:
        logger.error("Request timed out")
        return (
            jsonify(
                {
                    "error": "Request timed out. Please try with a simpler query or fewer iterations."
                }
            ),
            504,
        )
    except Exception as e:
        logger.error(f"Error in quick_summary API: {str(e)}", exc_info=True)
        return (
            jsonify(
                {
                    "error": "An internal error has occurred. Please try again later."
                }
            ),
            500,
        )


@api_blueprint.route("/generate_report", methods=["POST"])
@api_access_control
def api_generate_report():
    """
    Generate a comprehensive research report via REST API.

    POST /api/v1/generate_report
    {
        "query": "Impact of climate change on agriculture",
        "output_file": "/path/to/save/report.md",  # Optional
        "searches_per_section": 2,                 # Optional
        "model_name": "gpt-4",                     # Optional
        "temperature": 0.5                         # Optional
    }
    """
    data = request.json
    if not data or "query" not in data:
        return jsonify({"error": "Query parameter is required"}), 400

    query = data.get("query")
    params = {k: v for k, v in data.items() if k != "query"}

    try:
        # Import here to avoid circular imports
        from ..api.research_functions import generate_report

        # Set reasonable defaults for API use
        params.setdefault("searches_per_section", 1)
        params.setdefault("temperature", 0.7)

        logger.info(
            f"Processing generate_report request: query='{query}', params={params}"
        )

        result = generate_report(query, **params)

        # Don't return the full content for large reports
        if (
            result
            and "content" in result
            and isinstance(result["content"], str)
            and len(result["content"]) > 10000
        ):
            # Include a summary of the report content
            content_preview = (
                result["content"][:2000] + "... [Content truncated]"
            )
            result["content"] = content_preview
            result["content_truncated"] = True

        return jsonify(result)
    except TimeoutError:
        logger.error("Request timed out")
        return (
            jsonify(
                {"error": "Request timed out. Please try with a simpler query."}
            ),
            504,
        )
    except Exception as e:
        logger.error(f"Error in generate_report API: {str(e)}", exc_info=True)
        return (
            jsonify(
                {
                    "error": "An internal error has occurred. Please try again later."
                }
            ),
            500,
        )


@api_blueprint.route("/analyze_documents", methods=["POST"])
@api_access_control
def api_analyze_documents():
    """
    Search and analyze documents in a local collection via REST API.

    POST /api/v1/analyze_documents
    {
        "query": "neural networks in medicine",
        "collection_name": "research_papers",      # Required: local collection name
        "max_results": 20,                         # Optional: max results to return
        "temperature": 0.7,                        # Optional: LLM temperature
        "force_reindex": false                     # Optional: force reindexing
    }
    """
    data = request.json
    if not data or "query" not in data or "collection_name" not in data:
        return (
            jsonify(
                {
                    "error": "Both query and collection_name parameters are required"
                }
            ),
            400,
        )

    query = data.get("query")
    collection_name = data.get("collection_name")
    params = {
        k: v for k, v in data.items() if k not in ["query", "collection_name"]
    }

    try:
        result = analyze_documents(query, collection_name, **params)
        return jsonify(result)
    except Exception as e:
        logger.error(f"Error in analyze_documents API: {str(e)}", exc_info=True)
        return (
            jsonify(
                {
                    "error": "An internal error has occurred. Please try again later."
                }
            ),
            500,
        )
