"""Diagnostic endpoints for testing VS Code, LLM proxy, and agent functionality.

Thin orchestrator — individual checks live in _diag_*.py modules.

Covers:
  - VS Code Web reachability + login
  - LLM proxy health + models
  - Roo Code config in settings.json
  - Extensions installed (via docker exec)
  - Provider API keys configured
  - GitHub Copilot Chat conflict detection
  - Agent end-to-end completion test
"""

import asyncio
import structlog
from typing import Any

from fastapi import APIRouter, Request

from proxym.api._diag_agent import (
    check_agent_setup,
    check_copilot_conflict,
    test_agent_completion,
)
from proxym.api._diag_proxy import check_llm_proxy
from proxym.api._diag_providers import check_providers_config
from proxym.api._diag_roo import check_roo_cline_config
from proxym.api._diag_vscode import check_extensions, check_vscode_status

logger = structlog.get_logger()

router = APIRouter(prefix="/tests", tags=["diagnostics"])


@router.get("/status")
async def run_all_tests(request: Request):
    """Run all diagnostic tests and return comprehensive status."""
    test_names = [
        "vscode", "llm_proxy", "roo_cline",
        "extensions", "providers", "copilot_conflict",
        "agent_setup", "agent_test",
    ]
    tests = [
        check_vscode_status(),
        check_llm_proxy(base_url=str(request.base_url).rstrip("/")),
        check_roo_cline_config(),
        check_extensions(),
        check_providers_config(),
        check_copilot_conflict(),
        check_agent_setup(base_url=str(request.base_url).rstrip("/")),
        test_agent_completion(),
    ]

    results = await asyncio.gather(*tests, return_exceptions=True)

    processed_results: list[dict[str, Any]] = []
    for i, result in enumerate(results):
        if isinstance(result, Exception):
            processed_results.append({
                "service": test_names[i],
                "error": str(result),
                "status": "error",
            })
        else:
            processed_results.append(result)

    # Determine pass/fail per test
    def _is_passing(r: dict) -> bool:
        if r.get("status") == "error":
            return False
        if r.get("status") == "skipped":
            return True
        details = r.get("details") or {}
        if isinstance(details, dict) and details.get("skipped"):
            return True
        return bool(
            r.get(
                "reachable",
                r.get(
                    "configured",
                    r.get(
                        "success",
                        r.get(
                            "ready",
                            r.get(
                                "all_aliases_available",
                                not r.get("has_conflict", True),
                            ),
                        ),
                    ),
                ),
            )
        )

    def _as_issues(r: dict) -> list[str]:
        issues: list[str] = []

        if r.get("status") == "skipped":
            return issues

        if r.get("status") == "error" and r.get("error"):
            issues.append(str(r.get("error")))
            return issues

        details = r.get("details") or {}
        if isinstance(details, dict):
            if details.get("error"):
                issues.append(str(details["error"]))
            if details.get("docker_error"):
                issues.append(str(details["docker_error"]))

        if r.get("service") == "extensions":
            for e in r.get("missing_required") or []:
                issues.append(f"missing_required: {e}")
            for e in r.get("missing_vsix") or []:
                issues.append(f"missing_vsix: {e}")
            for e in r.get("conflicting") or []:
                issues.append(f"conflicting: {e}")

        if r.get("service") == "providers":
            for a in r.get("aliases") or []:
                if not a.get("available"):
                    issues.append(f"alias '{a.get('alias')}' provider '{a.get('provider')}' not configured")

        if r.get("service") == "copilot_conflict" and r.get("has_conflict"):
            for e in r.get("conflicting_extensions") or []:
                issues.append(f"conflicting_extension: {e}")
            if r.get("recommendation"):
                issues.append(str(r.get("recommendation")))

        if r.get("service") == "agent_setup":
            for c in r.get("checks") or []:
                if not c.get("pass"):
                    issues.append(f"{c.get('name')}: {c.get('detail')}")

        if r.get("service") == "vscode" and not r.get("reachable"):
            err = (details.get("error") if isinstance(details, dict) else None) or "VS Code not reachable"
            issues.append(str(err))

        if r.get("service") == "llm_proxy" and not r.get("reachable"):
            err = (details.get("error") if isinstance(details, dict) else None) or "Proxy not reachable"
            issues.append(str(err))

        if r.get("service") == "roo_cline" and not r.get("configured"):
            if isinstance(details, dict) and details.get("error"):
                issues.append(str(details.get("error")))
            else:
                issues.append("Roo Code not configured")

        if r.get("service") == "agent_test":
            skipped = (details.get("skipped") if isinstance(details, dict) else None)
            if skipped:
                issues.append(str(skipped))
            if isinstance(details, dict) and details.get("error"):
                issues.append(str(details.get("error")))

        return issues

    # Normalize for frontend summary/copy: ensure passed/message/issues exist.
    normalized: list[dict[str, Any]] = []
    for r in processed_results:
        passed_test = _is_passing(r)
        rr = dict(r)
        rr["passed"] = passed_test
        rr.setdefault("message", "OK" if passed_test else "Problem")
        rr["issues"] = _as_issues(rr) if not passed_test else []
        normalized.append(rr)

    processed_results = normalized

    passed = sum(1 for r in processed_results if r.get("passed"))
    failed = len(processed_results) - passed

    return {
        "overall_status": "healthy" if failed == 0 else "degraded",
        "passed": passed,
        "failed": failed,
        "total": len(processed_results),
        "tests": processed_results,
    }


@router.get("/vscode")
async def test_vscode():
    """Test VS Code Web connectivity."""
    return await check_vscode_status()


@router.get("/proxy")
async def test_proxy(request: Request):
    """Test LLM proxy connectivity."""
    return await check_llm_proxy(base_url=str(request.base_url).rstrip("/"))


@router.get("/roo")
async def test_roo():
    """Test Roo Code configuration."""
    return await check_roo_cline_config()


@router.get("/extensions")
async def test_extensions():
    """Check installed VS Code extensions."""
    return await check_extensions()


@router.get("/providers")
async def test_providers():
    """Check configured LLM providers and model aliases."""
    return await check_providers_config()


@router.get("/copilot")
async def test_copilot():
    """Detect GitHub Copilot extension conflicts."""
    return await check_copilot_conflict()


@router.get("/agent-setup")
async def test_agent_setup(request: Request):
    """Comprehensive agent readiness check."""
    return await check_agent_setup(base_url=str(request.base_url).rstrip("/"))


@router.get("/agent")
async def test_agent():
    """Test agent with a simple completion."""
    return await test_agent_completion()
