"""
Enhanced repo path resolution with better client context handling
This patch improves workspace detection and error messages
"""
import logging
from pathlib import Path
from typing import Any, Mapping
from ai_orchestrator.schemas.openai_compat import ChatCompletionRequest

logger = logging.getLogger(__name__)


def resolve_agent_repo_path_enhanced(
    self,
    request: ChatCompletionRequest,
    *,
    headers: Mapping[str, str] | None,
    client_context: dict[str, Any] | None = None,
) -> Path:
    """
    Enhanced repo path resolution that prioritizes client workspace detection.

    Resolution order:
    1. Explicit request (headers/body) - X-AIIQ-Repo-Path, aiiq_repo_path, repo_path
    2. Client workspace_root (from Cline, VS Code, etc.)
    3. Client current_working_directory
    4. Environment fallback (AIIQ_OPENAI_COMPAT_AGENT_REPO_PATH in .env)

    The FIRST valid path is returned - no hardcoded overrides!
    """
    # Get explicit override from request
    raw_value = self._request_override(
        request,
        headers=headers,
        header_name="X-AIIQ-Repo-Path",
        body_keys=("aiiq_repo_path", "repo_path", "workspace_path"),
    )

    # Build candidate list in priority order
    candidates: list[Any] = []

    # 1. Explicit request value (highest priority)
    if raw_value:
        candidates.append(("explicit_request", raw_value))

    # 2. Client context from VS Code, Cline, etc.
    if client_context:
        workspace_root = client_context.get("workspace_root")
        if workspace_root:
            candidates.append(("client_workspace_root", workspace_root))

        cwd = client_context.get("current_working_directory")
        if cwd:
            candidates.append(("client_cwd", cwd))

    # 3. Environment fallback (lowest priority - only if nothing else provided)
    env_fallback = self.settings.openai_compat_agent_repo_path
    if env_fallback:
        candidates.append(("environment_fallback", env_fallback))

    # Find first existing path
    fallback_path: Path | None = None
    fallback_source: str | None = None

    for source, candidate in candidates:
        if not candidate or candidate == "":
            continue

        path = Path(str(candidate)).expanduser().resolve()

        # Track the first valid candidate as fallback
        if fallback_path is None:
            fallback_path = path
            fallback_source = source

        # Check if path exists and is a directory
        if path.exists() and path.is_dir():
            logger.info(f"[Repo Path] Using {source}: {path}")
            return path

        # Log that we found a candidate but it doesn't exist
        logger.warning(f"[Repo Path] {source} specified but path does not exist: {candidate}")

    # If we have a fallback path but it doesn't exist, provide helpful error
    if fallback_path is not None:
        if not fallback_path.exists():
            # Check if this is the client's workspace that doesn't exist
            if fallback_source in ("client_workspace_root", "client_cwd"):
                raise OpenAICompatHTTPError(
                    f"Client workspace path does not exist: {fallback_path}\n"
                    f"Please verify the workspace path in your client (VS Code, Cline, etc.)",
                    status_code=400,
                    code="client_workspace_not_found",
                    param="repo_path",
                )
            else:
                raise OpenAICompatHTTPError(
                    f"Configured repo path does not exist: {fallback_path}\n"
                    f"Source: {fallback_source}\n"
                    f"Please ensure the path exists or update your configuration.",
                    status_code=404,
                    code="repo_path_not_found",
                    param="repo_path",
                )

    # No path found at all
    raise OpenAICompatHTTPError(
        "The `aiiq-agent` model requires a repo path.\n"
        "Provide one of:\n"
        "  1. In your client (VS Code/Cline): Ensure workspace_root is set\n"
        "  2. In request: Set repo_path in extra_body\n"
        "  3. In .env: Set AIIQ_OPENAI_COMPAT_AGENT_REPO_PATH\n\n"
        f"Detected client_context: {bool(client_context)}\n"
        f"Client workspace_root: {client_context.get('workspace_root') if client_context else 'N/A'}",
        status_code=400,
        code="agent_repo_path_required",
        param="model",
    )


def patch_openai_compat_service():
    """
    Patch OpenAICompatService to use enhanced repo path resolution.
    Call this during service initialization.
    """
    from ai_orchestrator.services import openai_compat_service

    # Store the original method
    original_resolve = openai_compat_service.OpenAICompatService._resolve_agent_repo_path

    # Replace with enhanced version (bound method will be created at runtime)
    openai_compat_service.OpenAICompatService._resolve_agent_repo_path = resolve_agent_repo_path_enhanced

    logger.info("Patched OpenAICompatService with enhanced repo path resolution")
    return original_resolve
