"""Flask routes for benchmark web interface."""

import time

from flask import Blueprint, jsonify, request
from loguru import logger

from ...database.session_context import get_user_db_session
from ...security.decorators import require_json_body
from ...web.auth.decorators import login_required
from ...security.rate_limiter import limiter
from local_deep_research.settings import SettingsManager
from ...llm.providers.base import normalize_provider
from ...web.utils.templates import render_template_with_defaults
from .benchmark_service import benchmark_service

# Create blueprint for benchmark routes
benchmark_bp = Blueprint("benchmark", __name__, url_prefix="/benchmark")

# NOTE: Routes use flask_session["username"] (not .get()) intentionally.
# @login_required guarantees the key exists; direct access fails fast
# if the decorator is ever removed.


@benchmark_bp.route("/")
@login_required
def index():
    """Benchmark dashboard page."""
    from flask import session as flask_session

    username = flask_session["username"]
    with get_user_db_session(username) as db_session:
        settings_manager = SettingsManager(db_session)

        # Load evaluation settings from database
        eval_settings = {
            "evaluation_provider": settings_manager.get_setting(
                "benchmark.evaluation.provider", "openai_endpoint"
            ),
            "evaluation_model": settings_manager.get_setting(
                "benchmark.evaluation.model", ""
            ),
            "evaluation_endpoint_url": settings_manager.get_setting(
                "benchmark.evaluation.endpoint_url", ""
            ),
            "evaluation_temperature": settings_manager.get_setting(
                "benchmark.evaluation.temperature", 0
            ),
        }

    return render_template_with_defaults(
        "pages/benchmark.html", eval_settings=eval_settings
    )


@benchmark_bp.route("/results")
@login_required
def results():
    """Benchmark results history page."""
    return render_template_with_defaults("pages/benchmark_results.html")


@benchmark_bp.route("/api/start", methods=["POST"])
@login_required
@require_json_body(error_message="No data provided")
def start_benchmark():
    """Start a new benchmark run."""
    try:
        data = request.get_json()

        # Extract configuration
        run_name = data.get("run_name")

        # Get search config from database instead of request
        from ...database.session_context import get_user_db_session
        from local_deep_research.settings import SettingsManager
        from flask import session as flask_session

        username = flask_session["username"]
        session_id = flask_session.get("session_id")

        # Try to get password from session store for background thread
        from ...database.session_passwords import session_password_store

        user_password = None
        if session_id:
            user_password = session_password_store.get_session_password(
                username, session_id
            )

        search_config = {}
        evaluation_config = {}
        datasets_config = data.get("datasets_config", {})

        with get_user_db_session(username) as db_session:
            # Use the logged-in user's settings
            settings_manager = SettingsManager(db_session)

            # Build search config from database settings
            search_config = {
                "iterations": int(
                    settings_manager.get_setting("search.iterations", 8)
                ),
                "questions_per_iteration": int(
                    settings_manager.get_setting(
                        "search.questions_per_iteration", 5
                    )
                ),
                "search_tool": settings_manager.get_setting(
                    "search.tool", "searxng"
                ),
                "search_strategy": settings_manager.get_setting(
                    "search.search_strategy", "focused_iteration"
                ),
                "model_name": settings_manager.get_setting("llm.model"),
                "provider": settings_manager.get_setting("llm.provider"),
                "temperature": float(
                    settings_manager.get_setting("llm.temperature", 0.7)
                ),
                "max_tokens": settings_manager.get_setting(
                    "llm.max_tokens", 30000
                ),
                "context_window_unrestricted": settings_manager.get_setting(
                    "llm.context_window_unrestricted", True
                ),
                "context_window_size": settings_manager.get_setting(
                    "llm.context_window_size", 128000
                ),
                "local_context_window_size": settings_manager.get_setting(
                    "llm.local_context_window_size", 8192
                ),
            }

            # Add provider-specific settings
            provider = normalize_provider(search_config.get("provider"))
            if provider == "openai_endpoint":
                search_config["openai_endpoint_url"] = (
                    settings_manager.get_setting("llm.openai_endpoint.url")
                )
                search_config["openai_endpoint_api_key"] = (
                    settings_manager.get_setting("llm.openai_endpoint.api_key")
                )
            elif provider == "openai":
                search_config["openai_api_key"] = settings_manager.get_setting(
                    "llm.openai.api_key"
                )
            elif provider == "anthropic":
                search_config["anthropic_api_key"] = (
                    settings_manager.get_setting("llm.anthropic.api_key")
                )

            # Get evaluation config from database settings or request
            if "evaluation_config" in data:
                evaluation_config = data["evaluation_config"]
            else:
                # Read evaluation config from database settings
                evaluation_provider = normalize_provider(
                    settings_manager.get_setting(
                        "benchmark.evaluation.provider", "openai_endpoint"
                    )
                )
                evaluation_model = settings_manager.get_setting(
                    "benchmark.evaluation.model", "anthropic/claude-3.7-sonnet"
                )
                evaluation_temperature = float(
                    settings_manager.get_setting(
                        "benchmark.evaluation.temperature", 0
                    )
                )

                evaluation_config = {
                    "provider": evaluation_provider,
                    "model_name": evaluation_model,
                    "temperature": evaluation_temperature,
                }

                # Add provider-specific settings for evaluation
                if evaluation_provider == "openai_endpoint":
                    evaluation_config["openai_endpoint_url"] = (
                        settings_manager.get_setting(
                            "benchmark.evaluation.endpoint_url",
                            "https://openrouter.ai/api/v1",
                        )
                    )
                    evaluation_config["openai_endpoint_api_key"] = (
                        settings_manager.get_setting(
                            "llm.openai_endpoint.api_key"
                        )
                    )
                elif evaluation_provider == "openai":
                    evaluation_config["openai_api_key"] = (
                        settings_manager.get_setting("llm.openai.api_key")
                    )
                elif evaluation_provider == "anthropic":
                    evaluation_config["anthropic_api_key"] = (
                        settings_manager.get_setting("llm.anthropic.api_key")
                    )

        # Validate datasets config
        if not datasets_config or not any(
            config.get("count", 0) > 0 for config in datasets_config.values()
        ):
            return jsonify(
                {
                    "error": "At least one dataset with count > 0 must be specified"
                }
            ), 400

        # Create benchmark run
        benchmark_run_id = benchmark_service.create_benchmark_run(
            run_name=run_name,
            search_config=search_config,
            evaluation_config=evaluation_config,
            datasets_config=datasets_config,
            username=username,
            user_password=user_password,
        )

        # Start benchmark
        success = benchmark_service.start_benchmark(
            benchmark_run_id, username, user_password
        )

        if success:
            return jsonify(
                {
                    "success": True,
                    "benchmark_run_id": benchmark_run_id,
                    "message": "Benchmark started successfully",
                }
            )
        return jsonify(
            {"success": False, "error": "Failed to start benchmark"}
        ), 500

    except Exception:
        logger.exception("Error starting benchmark")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/running", methods=["GET"])
@login_required
def get_running_benchmark():
    """Check if there's a running benchmark and return its ID."""
    try:
        from ...database.models.benchmark import BenchmarkRun, BenchmarkStatus
        from ...database.session_context import get_user_db_session
        from flask import session as flask_session

        username = flask_session["username"]
        with get_user_db_session(username) as session:
            # Find any benchmark that's currently running
            running_benchmark = (
                session.query(BenchmarkRun)
                .filter(BenchmarkRun.status == BenchmarkStatus.IN_PROGRESS)
                .order_by(BenchmarkRun.created_at.desc())
                .first()
            )

            if running_benchmark:
                return jsonify(
                    {
                        "success": True,
                        "benchmark_run_id": running_benchmark.id,
                        "run_name": running_benchmark.run_name,
                        "total_examples": running_benchmark.total_examples,
                        "completed_examples": running_benchmark.completed_examples,
                    }
                )
            return jsonify(
                {"success": False, "message": "No running benchmark found"}
            )

    except Exception:
        logger.exception("Error checking for running benchmark")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/status/<int:benchmark_run_id>", methods=["GET"])
@limiter.exempt
@login_required
def get_benchmark_status(benchmark_run_id: int):
    """Get status of a benchmark run."""
    try:
        from flask import session as flask_session

        username = flask_session["username"]
        status = benchmark_service.get_benchmark_status(
            benchmark_run_id, username
        )

        if status:
            logger.info(
                f"Returning status for benchmark {benchmark_run_id}: "
                f"completed={status.get('completed_examples')}, "
                f"overall_acc={status.get('overall_accuracy')}, "
                f"avg_time={status.get('avg_time_per_example')}, "
                f"estimated_remaining={status.get('estimated_time_remaining')}"
            )
            return jsonify({"success": True, "status": status})
        return jsonify(
            {"success": False, "error": "Benchmark run not found"}
        ), 404

    except Exception:
        logger.exception("Error getting benchmark status")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/cancel/<int:benchmark_run_id>", methods=["POST"])
@login_required
def cancel_benchmark(benchmark_run_id: int):
    """Cancel a running benchmark."""
    try:
        from flask import session as flask_session

        username = flask_session["username"]
        success = benchmark_service.cancel_benchmark(benchmark_run_id, username)

        if success:
            return jsonify(
                {"success": True, "message": "Benchmark cancelled successfully"}
            )
        return jsonify(
            {"success": False, "error": "Failed to cancel benchmark"}
        ), 500

    except Exception:
        logger.exception("Error cancelling benchmark")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/history", methods=["GET"])
@login_required
def get_benchmark_history():
    """Get list of recent benchmark runs."""
    try:
        from ...database.models.benchmark import BenchmarkRun
        from ...database.session_context import get_user_db_session
        from flask import session as flask_session

        username = flask_session["username"]
        with get_user_db_session(username) as session:
            # Get all benchmark runs (completed, failed, cancelled, or in-progress)
            runs = (
                session.query(BenchmarkRun)
                .order_by(BenchmarkRun.created_at.desc())
                .limit(50)
                .all()
            )

            # Format runs for display
            formatted_runs = []
            for run in runs:
                # Calculate average processing time from results
                avg_processing_time = None
                avg_search_results = None
                try:
                    from sqlalchemy import func

                    from ...database.models.benchmark import BenchmarkResult

                    avg_result = (
                        session.query(func.avg(BenchmarkResult.processing_time))
                        .filter(
                            BenchmarkResult.benchmark_run_id == run.id,
                            BenchmarkResult.processing_time.isnot(None),
                            BenchmarkResult.processing_time > 0,
                        )
                        .scalar()
                    )

                    if avg_result:
                        avg_processing_time = float(avg_result)
                except Exception:
                    logger.warning(
                        f"Error calculating avg processing time for run {run.id}"
                    )

                # Calculate average search results and total search requests from metrics
                total_search_requests = None
                try:
                    from ...database.models import SearchCall

                    # Get all results for this run to find research_ids
                    results = (
                        session.query(BenchmarkResult)
                        .filter(BenchmarkResult.benchmark_run_id == run.id)
                        .all()
                    )

                    research_ids = [
                        r.research_id for r in results if r.research_id
                    ]

                    if research_ids:
                        # SearchCall is in the same per-user DB, query directly
                        search_calls = (
                            session.query(SearchCall)
                            .filter(SearchCall.research_id.in_(research_ids))
                            .all()
                        )

                        # Group by research_id and calculate metrics per research session
                        research_results = {}
                        research_requests = {}

                        for call in search_calls:
                            if call.research_id:
                                if call.research_id not in research_results:
                                    research_results[call.research_id] = 0
                                    research_requests[call.research_id] = 0
                                research_results[call.research_id] += (
                                    call.results_count or 0
                                )
                                research_requests[call.research_id] += 1

                        # Calculate averages across research sessions
                        if research_results:
                            total_results = sum(research_results.values())
                            avg_search_results = total_results / len(
                                research_results
                            )

                            total_requests = sum(research_requests.values())
                            total_search_requests = total_requests / len(
                                research_requests
                            )

                except Exception:
                    logger.warning(
                        f"Error calculating search metrics for run {run.id}"
                    )

                formatted_runs.append(
                    {
                        "id": run.id,
                        "run_name": run.run_name or f"Benchmark #{run.id}",
                        "created_at": run.created_at.isoformat(),
                        # `start_time` is the wall-clock instant work began
                        # (status flipped to IN_PROGRESS); used by the YAML
                        # download for `date_tested` instead of the (broken)
                        # download-time stamp. NULL on rows that never started.
                        "start_time": run.start_time.isoformat()
                        if run.start_time
                        else None,
                        # `ldr_version` is captured by start_benchmark; NULL
                        # on rows created before migration 0014. The YAML
                        # download substitutes "unknown (pre-0014 run)".
                        # `settings_snapshot` is intentionally NOT included
                        # here — it's ~184KB per run and would balloon the
                        # history list response. Loaded on-demand from
                        # /api/results/<id>/export when YAML is downloaded.
                        "ldr_version": run.ldr_version,
                        "total_examples": run.total_examples,
                        "completed_examples": run.completed_examples,
                        "overall_accuracy": run.overall_accuracy,
                        "status": run.status.value,
                        "search_config": run.search_config,
                        "evaluation_config": run.evaluation_config,
                        "datasets_config": run.datasets_config,
                        "avg_processing_time": avg_processing_time,
                        "avg_search_results": avg_search_results,
                        "total_search_requests": total_search_requests,
                    }
                )

        return jsonify({"success": True, "runs": formatted_runs})

    except Exception:
        logger.exception("Error getting benchmark history")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/results/<int:benchmark_run_id>", methods=["GET"])
@limiter.exempt
@login_required
def get_benchmark_results(benchmark_run_id: int):
    """Get detailed results for a benchmark run."""
    try:
        from ...database.models.benchmark import BenchmarkResult
        from ...database.session_context import get_user_db_session
        from flask import session as flask_session

        logger.info(f"Getting results for benchmark {benchmark_run_id}")
        username = flask_session["username"]

        # First sync any pending results from active runs
        benchmark_service.sync_pending_results(benchmark_run_id, username)
        with get_user_db_session(username) as session:
            # Get recent results (limit to last 10)
            limit = int(request.args.get("limit", 10))

            results = (
                session.query(BenchmarkResult)
                .filter(BenchmarkResult.benchmark_run_id == benchmark_run_id)
                .order_by(BenchmarkResult.id.desc())  # Most recent first
                .limit(limit)
                .all()
            )

            logger.info(f"Found {len(results)} results")

            # Build a map of research_id to total search results
            search_results_by_research_id = {}
            try:
                from ...database.models import SearchCall

                # Get all unique research_ids from our results
                research_ids = [r.research_id for r in results if r.research_id]

                if research_ids:
                    # SearchCall is in the same per-user DB, query directly
                    all_search_calls = (
                        session.query(SearchCall)
                        .filter(SearchCall.research_id.in_(research_ids))
                        .all()
                    )

                    # Group search results by research_id
                    for call in all_search_calls:
                        if call.research_id:
                            if (
                                call.research_id
                                not in search_results_by_research_id
                            ):
                                search_results_by_research_id[
                                    call.research_id
                                ] = 0
                            search_results_by_research_id[call.research_id] += (
                                call.results_count or 0
                            )

                    logger.info(
                        f"Found search metrics for {len(search_results_by_research_id)} research IDs from {len(all_search_calls)} total search calls"
                    )
                    logger.debug(
                        f"Research IDs from results: {research_ids[:5] if len(research_ids) > 5 else research_ids}"
                    )
                    logger.debug(
                        f"Search results by research_id: {dict(list(search_results_by_research_id.items())[:5])}"
                    )
            except Exception:
                logger.exception(
                    f"Error getting search metrics for benchmark {benchmark_run_id}"
                )

            # Format results for UI display
            formatted_results = []
            for result in results:
                # Get search result count using research_id
                search_result_count = 0

                try:
                    if (
                        result.research_id
                        and result.research_id in search_results_by_research_id
                    ):
                        search_result_count = search_results_by_research_id[
                            result.research_id
                        ]
                        logger.debug(
                            f"Found {search_result_count} search results for research_id {result.research_id}"
                        )

                except Exception:
                    logger.exception(
                        f"Error getting search results for result {result.example_id}"
                    )

                formatted_results.append(
                    {
                        "example_id": result.example_id,
                        "dataset_type": result.dataset_type.value,
                        "question": result.question,
                        "correct_answer": result.correct_answer,
                        "model_answer": result.extracted_answer,
                        "full_response": result.response,
                        "is_correct": result.is_correct,
                        "confidence": result.confidence,
                        "grader_response": result.grader_response,
                        "processing_time": result.processing_time,
                        "search_result_count": search_result_count,
                        "sources": result.sources,
                        "completed_at": result.completed_at.isoformat()
                        if result.completed_at
                        else None,
                    }
                )

            return jsonify({"success": True, "results": formatted_results})

    except Exception:
        logger.exception("Error getting benchmark results")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route(
    "/api/results/<int:benchmark_run_id>/export", methods=["GET"]
)
@login_required
def export_benchmark_results(benchmark_run_id: int):
    """Get lightweight results for YAML export plus run-level provenance.

    Returns a `metadata` block alongside the per-result rows so the YAML
    download path can stamp the version/settings that ran the benchmark
    instead of falling back to download-time values. Pre-0014 rows return
    NULL for the new metadata fields. The `success: True` envelope is
    preserved so the existing JS contract (5 callsites in
    benchmark_results.html) keeps working.
    """
    try:
        from sqlalchemy.orm import load_only

        from ...database.models.benchmark import (
            BenchmarkResult,
            BenchmarkRun,
        )
        from ...database.session_context import get_user_db_session
        from flask import request, session as flask_session

        username = flask_session["username"]
        # The ~184KB settings snapshot is only loaded/returned when the
        # client opts in (Export -> "Include settings snapshot"); the
        # default summary download skips it to avoid transferring a blob it
        # would discard.
        include_settings = request.args.get("include_settings", "").lower() in (
            "1",
            "true",
        )
        logger.info(
            "Exporting benchmark results for run {} by user {}",
            benchmark_run_id,
            username,
        )
        with get_user_db_session(username) as session:
            # Fetch only the provenance columns we need from BenchmarkRun.
            # `load_only` keeps us off the heavy JSON config blobs (and the
            # settings_snapshot blob unless it was requested).
            run_columns = [
                BenchmarkRun.ldr_version,
                BenchmarkRun.start_time,
                BenchmarkRun.created_at,
            ]
            if include_settings:
                run_columns.append(BenchmarkRun.settings_snapshot)
            run = (
                session.query(BenchmarkRun)
                .options(load_only(*run_columns))
                .filter(BenchmarkRun.id == benchmark_run_id)
                .one_or_none()
            )

            results = (
                session.query(BenchmarkResult)
                .options(
                    load_only(
                        BenchmarkResult.example_id,
                        BenchmarkResult.dataset_type,
                        BenchmarkResult.question,
                        BenchmarkResult.correct_answer,
                        BenchmarkResult.extracted_answer,
                        BenchmarkResult.is_correct,
                        BenchmarkResult.confidence,
                        BenchmarkResult.processing_time,
                        BenchmarkResult.completed_at,
                    )
                )
                .filter(BenchmarkResult.benchmark_run_id == benchmark_run_id)
                .order_by(BenchmarkResult.id.asc())
                .all()
            )

            formatted = []
            for r in results:
                formatted.append(
                    {
                        "example_id": r.example_id,
                        "dataset_type": r.dataset_type.value,
                        "question": r.question,
                        "correct_answer": r.correct_answer,
                        "model_answer": r.extracted_answer,
                        "is_correct": r.is_correct,
                        "confidence": r.confidence,
                        "processing_time": r.processing_time,
                        "completed_at": r.completed_at.isoformat()
                        if r.completed_at
                        else None,
                    }
                )

            # Build metadata block. Each field is independently null-checked
            # so a pre-0014 row, or an in-flight run with no start_time,
            # serializes cleanly as JSON null.
            if run is not None:
                started_at = (
                    run.start_time.isoformat()
                    if run.start_time
                    else (
                        run.created_at.isoformat() if run.created_at else None
                    )
                )
                metadata = {
                    "ldr_version": run.ldr_version,
                    "started_at": started_at,
                    "settings_snapshot": (
                        run.settings_snapshot if include_settings else None
                    ),
                }
            else:
                metadata = {
                    "ldr_version": None,
                    "started_at": None,
                    "settings_snapshot": None,
                }

            logger.info(
                "Exported {} results for benchmark run {}",
                len(formatted),
                benchmark_run_id,
            )
            return jsonify(
                {
                    "success": True,
                    "metadata": metadata,
                    "results": formatted,
                }
            )

    except Exception:
        logger.exception("Error exporting benchmark results")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/configs", methods=["GET"])
@login_required
def get_saved_configs():
    """Get list of saved benchmark configurations."""
    try:
        # TODO: Implement saved configs retrieval from database
        # For now return default configs
        default_configs = [
            {
                "id": 1,
                "name": "Quick Test",
                "description": "Fast benchmark with minimal examples",
                "search_config": {
                    "iterations": 3,
                    "questions_per_iteration": 3,
                    "search_tool": "searxng",
                    "search_strategy": "focused_iteration",
                },
                "datasets_config": {
                    "simpleqa": {"count": 10},
                    "browsecomp": {"count": 5},
                },
            },
            {
                "id": 2,
                "name": "Standard Evaluation",
                "description": "Comprehensive benchmark with standard settings",
                "search_config": {
                    "iterations": 8,
                    "questions_per_iteration": 5,
                    "search_tool": "searxng",
                    "search_strategy": "focused_iteration",
                },
                "datasets_config": {
                    "simpleqa": {"count": 50},
                    "browsecomp": {"count": 25},
                },
            },
        ]

        return jsonify({"success": True, "configs": default_configs})

    except Exception:
        logger.exception("Error getting saved configs")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/start-simple", methods=["POST"])
@login_required
@require_json_body()
def start_benchmark_simple():
    """Start a benchmark using current database settings."""
    try:
        data = request.get_json()
        datasets_config = data.get("datasets_config", {})

        # Validate datasets
        if not datasets_config or not any(
            config.get("count", 0) > 0 for config in datasets_config.values()
        ):
            return jsonify(
                {
                    "error": "At least one dataset with count > 0 must be specified"
                }
            ), 400

        # Get current settings from database
        from flask import session as flask_session

        username = flask_session["username"]
        session_id = flask_session.get("session_id")

        # Try to get password from session store for background thread
        from ...database.session_passwords import session_password_store

        user_password = None
        if session_id:
            user_password = session_password_store.get_session_password(
                username, session_id
            )

        with get_user_db_session(username, user_password) as session:
            # For benchmarks, use a default test username
            settings_manager = SettingsManager(session)

            # Build search config from database settings
            search_config = {
                "iterations": int(
                    settings_manager.get_setting("search.iterations", 8)
                ),
                "questions_per_iteration": int(
                    settings_manager.get_setting(
                        "search.questions_per_iteration", 5
                    )
                ),
                "search_tool": settings_manager.get_setting(
                    "search.tool", "searxng"
                ),
                "search_strategy": settings_manager.get_setting(
                    "search.search_strategy", "focused_iteration"
                ),
                "model_name": settings_manager.get_setting("llm.model"),
                "provider": settings_manager.get_setting("llm.provider"),
                "temperature": float(
                    settings_manager.get_setting("llm.temperature", 0.7)
                ),
                "max_tokens": settings_manager.get_setting(
                    "llm.max_tokens", 30000
                ),
                "context_window_unrestricted": settings_manager.get_setting(
                    "llm.context_window_unrestricted", True
                ),
                "context_window_size": settings_manager.get_setting(
                    "llm.context_window_size", 128000
                ),
                "local_context_window_size": settings_manager.get_setting(
                    "llm.local_context_window_size", 8192
                ),
            }

            # Add provider-specific settings
            provider = normalize_provider(search_config.get("provider"))
            if provider == "openai_endpoint":
                search_config["openai_endpoint_url"] = (
                    settings_manager.get_setting("llm.openai_endpoint.url")
                )
                search_config["openai_endpoint_api_key"] = (
                    settings_manager.get_setting("llm.openai_endpoint.api_key")
                )
            elif provider == "openai":
                search_config["openai_api_key"] = settings_manager.get_setting(
                    "llm.openai.api_key"
                )
            elif provider == "anthropic":
                search_config["anthropic_api_key"] = (
                    settings_manager.get_setting("llm.anthropic.api_key")
                )

            # Read evaluation config from database settings
            evaluation_provider = normalize_provider(
                settings_manager.get_setting(
                    "benchmark.evaluation.provider", "openai_endpoint"
                )
            )
            evaluation_model = settings_manager.get_setting(
                "benchmark.evaluation.model", "anthropic/claude-3.7-sonnet"
            )
            evaluation_temperature = float(
                settings_manager.get_setting(
                    "benchmark.evaluation.temperature", 0
                )
            )

            evaluation_config = {
                "provider": evaluation_provider,
                "model_name": evaluation_model,
                "temperature": evaluation_temperature,
            }

            # Add provider-specific settings for evaluation
            if evaluation_provider == "openai_endpoint":
                evaluation_config["openai_endpoint_url"] = (
                    settings_manager.get_setting(
                        "benchmark.evaluation.endpoint_url",
                        "https://openrouter.ai/api/v1",
                    )
                )
                evaluation_config["openai_endpoint_api_key"] = (
                    settings_manager.get_setting("llm.openai_endpoint.api_key")
                )
            elif evaluation_provider == "openai":
                evaluation_config["openai_api_key"] = (
                    settings_manager.get_setting("llm.openai.api_key")
                )
            elif evaluation_provider == "anthropic":
                evaluation_config["anthropic_api_key"] = (
                    settings_manager.get_setting("llm.anthropic.api_key")
                )

        # Create and start benchmark
        benchmark_run_id = benchmark_service.create_benchmark_run(
            run_name=f"Quick Benchmark - {data.get('run_name', '')}",
            search_config=search_config,
            evaluation_config=evaluation_config,
            datasets_config=datasets_config,
            username=username,
            user_password=user_password,
        )

        success = benchmark_service.start_benchmark(
            benchmark_run_id, username, user_password
        )

        if success:
            return jsonify(
                {
                    "success": True,
                    "benchmark_run_id": benchmark_run_id,
                    "message": "Benchmark started with current settings",
                }
            )
        return jsonify(
            {"success": False, "error": "Failed to start benchmark"}
        ), 500

    except Exception:
        logger.exception("Error starting simple benchmark")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/validate-config", methods=["POST"])
@login_required
def validate_config():
    """Validate a benchmark configuration.

    Note: not using @require_json_body because this endpoint returns
    {"valid": False, "errors": [...]} which doesn't match the decorator's
    three standard error formats.
    """
    try:
        data = request.get_json()

        if not isinstance(data, dict):
            return jsonify({"valid": False, "errors": ["No data provided"]})

        errors = []

        # Validate search config
        search_config = data.get("search_config", {})
        if not search_config.get("search_tool"):
            errors.append("Search tool is required")
        if not search_config.get("search_strategy"):
            errors.append("Search strategy is required")

        # Validate datasets config
        datasets_config = data.get("datasets_config", {})
        if not datasets_config:
            errors.append("At least one dataset must be configured")

        total_examples = sum(
            config.get("count", 0) for config in datasets_config.values()
        )
        if total_examples == 0:
            errors.append("Total examples must be greater than 0")

        return jsonify(
            {
                "valid": len(errors) == 0,
                "errors": errors,
                "total_examples": total_examples,
            }
        )

    except Exception:
        logger.exception("Error validating config")
        return jsonify(
            {"valid": False, "errors": ["An internal error has occurred."]}
        ), 500


@benchmark_bp.route("/api/search-quality", methods=["GET"])
@limiter.exempt
@login_required
def get_search_quality():
    """Get current search quality metrics from rate limiting data."""
    try:
        from flask import session as flask_session

        from ...database.models import RateLimitEstimate

        username = flask_session["username"]
        quality_stats = []

        with get_user_db_session(username) as db_session:
            estimates = db_session.query(RateLimitEstimate).all()
            for est in estimates:
                quality_stats.append(
                    {
                        "engine_type": est.engine_type,
                        "total_attempts": est.total_attempts,
                        "success_rate": round(est.success_rate * 100, 1),
                        "status": (
                            "EXCELLENT"
                            if est.success_rate >= 0.95
                            else "GOOD"
                            if est.success_rate >= 0.9
                            else "CAUTION"
                            if est.success_rate >= 0.75
                            else "WARNING"
                            if est.success_rate >= 0.5
                            else "CRITICAL"
                        ),
                    }
                )

        return jsonify(
            {
                "success": True,
                "search_quality": quality_stats,
                "timestamp": time.time(),
            }
        )

    except Exception:
        logger.exception("Error getting search quality")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500


@benchmark_bp.route("/api/delete/<int:benchmark_run_id>", methods=["DELETE"])
@login_required
def delete_benchmark_run(benchmark_run_id: int):
    """Delete a benchmark run and all its results."""
    try:
        from ...database.models.benchmark import (
            BenchmarkProgress,
            BenchmarkResult,
            BenchmarkRun,
        )
        from ...database.session_context import get_user_db_session
        from flask import session as flask_session

        username = flask_session["username"]
        with get_user_db_session(username) as session:
            # Check if benchmark run exists
            benchmark_run = (
                session.query(BenchmarkRun)
                .filter(BenchmarkRun.id == benchmark_run_id)
                .first()
            )

            if not benchmark_run:
                return jsonify(
                    {"success": False, "error": "Benchmark run not found"}
                ), 404

            # Prevent deletion of running benchmarks
            if benchmark_run.status.value == "in_progress":
                return jsonify(
                    {
                        "success": False,
                        "error": "Cannot delete a running benchmark. Cancel it first.",
                    }
                ), 400

            # Delete related records (cascade should handle this, but being explicit)
            session.query(BenchmarkResult).filter(
                BenchmarkResult.benchmark_run_id == benchmark_run_id
            ).delete()

            session.query(BenchmarkProgress).filter(
                BenchmarkProgress.benchmark_run_id == benchmark_run_id
            ).delete()

            # Delete the benchmark run
            session.delete(benchmark_run)
            session.commit()

            logger.info(f"Deleted benchmark run {benchmark_run_id}")
            return jsonify(
                {
                    "success": True,
                    "message": f"Benchmark run {benchmark_run_id} deleted successfully",
                }
            )

    except Exception:
        logger.exception(f"Error deleting benchmark run {benchmark_run_id}")
        return jsonify(
            {"success": False, "error": "An internal error has occurred."}
        ), 500
