"""Adapter for rlm_runner that executes Recall's RLM stack."""

from __future__ import annotations

import os
from typing import Any

from .conversation import build_conversation_context
from .execution_context import (
    DEFAULT_MAX_CALLS,
    DEFAULT_MAX_DEPTH,
    DEFAULT_MAX_OUTPUT_CHARS,
)
from .fingerprint import build_request_fingerprint, log_fingerprint
from .llm_client import create_llm_client_with_credentials
from .modelrelay import ModelResolutionPolicy, resolve_root_model, resolve_subcall_model
from .rlm import run_rlm


def _require_field(payload: dict[str, Any], key: str) -> str:
    value = payload.get(key)
    if not isinstance(value, str) or not value.strip():
        raise ValueError(f"Missing required field: {key}")
    return value


def run(request: dict[str, Any]) -> dict[str, Any]:
    """Execute a Recall RLM request and return a host-compatible response dict."""
    question = _require_field(request, "question")
    db_path = _require_field(request, "db_path")
    contacts_db_path = request.get("contacts_db_path") or os.environ.get("CONTACTS_DB_PATH")

    auth_type = request.get("auth_type", "api_key")
    customer_token_raw = request.get("customer_token")
    api_key_raw = request.get("api_key")

    resolved_customer_token: str | None = None
    resolved_api_key: str | None = None

    if auth_type == "customer_token" and isinstance(customer_token_raw, str) and customer_token_raw.strip():
        resolved_customer_token = customer_token_raw.strip()
    elif isinstance(api_key_raw, str) and api_key_raw.strip():
        resolved_api_key = api_key_raw.strip()

    llm_client = create_llm_client_with_credentials(
        api_key=resolved_api_key,
        customer_token=resolved_customer_token,
    )

    root_model = request.get("root_model")
    if not (isinstance(root_model, str) and root_model.strip()):
        root_model = request.get("model")
    subcall_model = request.get("subcall_model")
    max_depth = int(request.get("max_depth", DEFAULT_MAX_DEPTH))
    max_calls = int(request.get("max_calls", DEFAULT_MAX_CALLS))
    max_output_chars = int(request.get("max_output_chars", DEFAULT_MAX_OUTPUT_CHARS))
    verbose = bool(request.get("verbose", False))
    conversation_context = request.get("conversation_context")
    conversation_messages = request.get("conversation_messages")
    conversation_summary = request.get("conversation_summary")
    tips_profile_raw = request.get("tips_profile")
    tips_profile = tips_profile_raw if isinstance(tips_profile_raw, str) and tips_profile_raw.strip() else None

    policy = ModelResolutionPolicy(allow_env=False)
    resolved_root_model = resolve_root_model(root_model if isinstance(root_model, str) else None, policy=policy)
    resolved_subcall_model = resolve_subcall_model(
        subcall_model if isinstance(subcall_model, str) else None,
        root_fallback=root_model if isinstance(root_model, str) else None,
        policy=policy,
    )

    updated_summary = conversation_summary if isinstance(conversation_summary, str) else None
    if isinstance(conversation_context, str) and conversation_context.strip():
        resolved_context = conversation_context.strip()
    elif isinstance(conversation_messages, list) or isinstance(conversation_summary, str):
        resolved_context, updated_summary = build_conversation_context(
            messages=conversation_messages if isinstance(conversation_messages, list) else [],
            summary=conversation_summary if isinstance(conversation_summary, str) else None,
            model=resolved_root_model,
            llm_client=llm_client,
        )
    else:
        resolved_context = None

    fingerprint = build_request_fingerprint(
        question=question,
        db_path=db_path,
        contacts_db_path=contacts_db_path if isinstance(contacts_db_path, str) else None,
        conversation_context=resolved_context,
        max_depth=max(1, max_depth),
        max_calls=max(1, max_calls),
        max_output_chars=max(1, max_output_chars),
        root_model=resolved_root_model,
        subcall_model=resolved_subcall_model,
    )
    log_fingerprint(fingerprint)

    result = run_rlm(
        question=question,
        db_path=db_path,
        contacts_db_path=contacts_db_path if isinstance(contacts_db_path, str) else None,
        conversation_context=resolved_context,
        max_depth=max(1, max_depth),
        max_calls=max(1, max_calls),
        max_output_chars=max(1, max_output_chars),
        verbose=verbose,
        root_model=resolved_root_model,
        subcall_model=resolved_subcall_model,
        llm_client=llm_client,
        tips_profile=tips_profile,
    )

    return {
        "answer": result.answer,
        "retrieved_guids": result.retrieved_guids,
        "iterations": result.iterations,
        "sub_calls_made": result.sub_calls_made,
        "total_tokens": result.total_tokens,
        "error": result.error,
        "conversation_summary": updated_summary,
        "fingerprint": fingerprint,
    }
