"""Entrypoint: run CODE_QA golden evaluation and write artifacts + summary."""

from __future__ import annotations

import sys
from datetime import datetime
from pathlib import Path

_agent_root = Path(__file__).resolve().parents[4]
if str(_agent_root) not in sys.path:
    sys.path.insert(0, str(_agent_root))
_src = _agent_root / "src"
if _src.exists() and str(_src) not in sys.path:
    sys.path.insert(0, str(_src))

# Load .env from project root so DATABASE_URL is available
from app.modules.shared.env_loader import load_workspace_env

from tests.pipeline_setup.suite_01_synthetic.code_qa_eval.artifacts import dump_run_artifact, write_batch_summary
from tests.pipeline_setup.suite_01_synthetic.code_qa_eval.config import EvalConfig
from tests.pipeline_setup.suite_01_synthetic.code_qa_eval.runner import run_eval


class _TeeStream:
    def __init__(self, *streams) -> None:
        self._streams = streams

    def write(self, data: str) -> int:
        for stream in self._streams:
            stream.write(data)
        return len(data)

    def flush(self) -> None:
        for stream in self._streams:
            stream.flush()


def _check_db_available() -> bool:
    """Try to connect to the database; return False if unavailable."""
    try:
        from sqlalchemy import text
        from app.modules.shared.db import get_engine
        with get_engine().connect() as conn:
            conn.execute(text("SELECT 1"))
        return True
    except Exception:
        return False


def main() -> None:
    # Workspace root (agent repo) for .env; pipeline_setup root for fixtures/golden/test_results
    workspace_root = Path(__file__).resolve().parents[3]
    pipeline_root = Path(__file__).resolve().parents[1]
    load_workspace_env(workspace_root)
    config = EvalConfig.from_env(project_root=pipeline_root)
    run_id = datetime.now().strftime("%Y%m%d_%H%M%S")
    results_run_dir = config.test_results_dir / run_id
    results_run_dir.mkdir(parents=True, exist_ok=True)
    console_log_path = results_run_dir / "console_output.txt"

    original_stdout = sys.stdout
    original_stderr = sys.stderr
    with console_log_path.open("w", encoding="utf-8") as log_file:
        sys.stdout = _TeeStream(original_stdout, log_file)
        sys.stderr = _TeeStream(original_stderr, log_file)
        try:
            _run_with_logging(config, results_run_dir, run_id)
        finally:
            sys.stdout.flush()
            sys.stderr.flush()
            sys.stdout = original_stdout
            sys.stderr = original_stderr


def _run_with_logging(config: EvalConfig, results_run_dir: Path, run_id: str) -> None:
    print(f"Console log: {results_run_dir / 'console_output.txt'}")

    if not config.repo_path.exists():
        print(f"Repo path not found: {config.repo_path}", file=sys.stderr)
        sys.exit(1)
    if not config.golden_cases_path.exists():
        print(f"Golden cases not found: {config.golden_cases_path}", file=sys.stderr)
        sys.exit(1)

    if not _check_db_available():
        print(
            "Database is not available. Evaluation requires a running PostgreSQL instance.\n"
            "Set DATABASE_URL (e.g. postgresql+psycopg://user:pass@localhost:5432/db) or start the DB (e.g. docker-compose up -d db).",
            file=sys.stderr,
        )
        sys.exit(1)

    print(f"Running evaluation: repo={config.repo_path}, fixture={config.use_fixture}")
    print(f"Results: {results_run_dir}")

    results = run_eval(config)
    for r in results:
        dump_run_artifact(r, results_run_dir, run_id=run_id)

    summary_path = write_batch_summary(results, config.test_results_dir, run_id=run_id)
    passed = sum(1 for r in results if r.passed)
    total = len(results)
    print(f"\n{passed}/{total} cases passed. Summary: {summary_path}")
    for r in results:
        if not r.passed:
            print(f"  FAIL {r.case.id}: {'; '.join(r.mismatches)}")
    sys.exit(0 if passed == total else 1)


if __name__ == "__main__":
    main()
