"""
CLI entry point for Clew-Bench.

Usage:
    python -m bench --workload bench/workloads/auth_epic.json --trials 1
    python -m bench --help
"""

from __future__ import annotations

import argparse
import asyncio
import logging
import os
import sys
from pathlib import Path

from .arena import ArenaHarness, load_workload
from .coding_llm import CodingLLM
from .engines.clew import ClewContextEngine
from .engines.standard_rag import StandardRAGEngine
from .judge import JudgeLLM
from .report import format_text_report, write_json_report, write_text_report

logger = logging.getLogger("clew.bench")

DEFAULT_WORKLOAD = Path(__file__).parent / "workloads" / "auth_epic.json"
DEFAULT_RESULTS_DIR = Path("results")


def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        prog="clew-bench",
        description="Clew-Bench: Comparative Agent Arena for empirical validation",
    )
    parser.add_argument(
        "--workload",
        type=Path,
        default=DEFAULT_WORKLOAD,
        help="Path to workload JSON file (default: bench/workloads/auth_epic.json)",
    )
    parser.add_argument(
        "--clew-url",
        default=os.environ.get("CLEW_API_URL", "http://localhost:8000"),
        help="Clew API base URL (default: $CLEW_API_URL or http://localhost:8000)",
    )
    parser.add_argument(
        "--qdrant-url",
        default=os.environ.get("QDRANT_URL", "http://localhost:6333"),
        help="Qdrant REST URL (default: $QDRANT_URL or http://localhost:6333)",
    )
    parser.add_argument(
        "--embedding-url",
        default=os.environ.get("EMBEDDING_URL", "https://api.openai.com"),
        help="Embedding API URL (default: $EMBEDDING_URL or https://api.openai.com)",
    )
    parser.add_argument(
        "--repo-path",
        default=".",
        help="Path to the starter repository under test (default: .)",
    )
    parser.add_argument(
        "--trials",
        type=int,
        default=1,
        help="Number of experiment trials to run (default: 1)",
    )
    parser.add_argument(
        "--output-dir",
        type=Path,
        default=DEFAULT_RESULTS_DIR,
        help="Directory for result files (default: results/)",
    )
    parser.add_argument(
        "--coding-model",
        default="claude-sonnet-4-20250514",
        help="Anthropic model ID for code generation",
    )
    parser.add_argument(
        "--judge-model",
        default="gemini-1.5-pro",
        help="Google model ID for judging",
    )
    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
        help="Enable debug logging",
    )
    return parser.parse_args(argv)


def _check_api_keys() -> tuple[str, str, str]:
    """Validate required API keys are set."""
    anthropic_key = os.environ.get("ANTHROPIC_API_KEY", "")
    gemini_key = os.environ.get("GEMINI_API_KEY", "")
    openai_key = os.environ.get("OPENAI_API_KEY", "")

    missing = []
    if not anthropic_key:
        missing.append("ANTHROPIC_API_KEY")
    if not gemini_key:
        missing.append("GEMINI_API_KEY")
    if not openai_key:
        missing.append("OPENAI_API_KEY")

    if missing:
        print(f"Error: Missing required environment variables: {', '.join(missing)}", file=sys.stderr)
        print("Set them before running clew-bench.", file=sys.stderr)
        sys.exit(1)

    return anthropic_key, gemini_key, openai_key


async def run(args: argparse.Namespace) -> None:
    """Run the benchmark experiment."""
    anthropic_key, gemini_key, _openai_key = _check_api_keys()

    workload = load_workload(args.workload)
    logger.info(
        "Loaded workload: %s (%d epics, %d tickets, %d traps)",
        workload.workload_id,
        len(workload.epics),
        len(workload.all_tickets),
        workload.trap_count,
    )

    clew_engine = ClewContextEngine(api_url=args.clew_url)
    standard_engine = StandardRAGEngine(
        qdrant_url=args.qdrant_url,
        embedding_url=args.embedding_url,
        api_key=_openai_key,
    )
    coding_llm = CodingLLM(api_key=anthropic_key, model=args.coding_model)
    judge = JudgeLLM(api_key=gemini_key, model=args.judge_model)

    harness = ArenaHarness(
        workload=workload,
        clew_engine=clew_engine,
        standard_engine=standard_engine,
        coding_llm=coding_llm,
        judge=judge,
    )

    try:
        for trial in range(1, args.trials + 1):
            logger.info("=== Trial %d/%d ===", trial, args.trials)

            result = await harness.run_experiment(trial_number=trial)

            # Print text report to stdout
            report = format_text_report(result)
            print(report)

            # Write result files
            args.output_dir.mkdir(parents=True, exist_ok=True)
            json_path = args.output_dir / f"trial_{trial:03d}.json"
            text_path = args.output_dir / f"trial_{trial:03d}.txt"
            write_json_report(result, json_path)
            write_text_report(result, text_path)
            logger.info("Results written to %s and %s", json_path, text_path)

    finally:
        await clew_engine.close()
        await standard_engine.close()
        await coding_llm.close()
        await judge.close()


def main(argv: list[str] | None = None) -> None:
    args = parse_args(argv)
    log_level = logging.DEBUG if args.verbose else logging.INFO
    logging.basicConfig(
        level=log_level,
        format="%(asctime)s %(name)s %(levelname)s %(message)s",
        datefmt="%H:%M:%S",
    )
    asyncio.run(run(args))


if __name__ == "__main__":
    main()
