"""GCP-only Cloud SQL adapter over the unchanged shared Leo DB-context plugin."""

from __future__ import annotations

import hashlib
import importlib.util
import json
import os
import subprocess
import sys
from collections.abc import Callable
from datetime import datetime, timezone
from pathlib import Path
from types import ModuleType
from typing import Any

HERE = Path(__file__).resolve().parent


def _load_base() -> ModuleType:
    path = HERE / "base.py"
    if path.is_symlink() or not path.is_file():
        raise RuntimeError("bound Leo DB-context plugin is unavailable")
    spec = importlib.util.spec_from_file_location("livingip_leo_db_context_base", path)
    if spec is None or spec.loader is None:
        raise RuntimeError("bound Leo DB-context plugin is unavailable")
    module = importlib.util.module_from_spec(spec)
    sys.modules[spec.name] = module
    spec.loader.exec_module(module)
    return module


base = _load_base()


def _load_database_snapshot(
    user_message: str,
    *,
    conversation_history: Any = None,
    hermes_home: Path | None = None,
    runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
) -> dict[str, Any]:
    """Load one private, excerpt-bearing Cloud SQL snapshot without VPS fallback."""

    query = str(user_message or "")[: base.MAX_QUERY_CHARS]
    contextual = getattr(base, "_contextual_retrieval_query", lambda value, _history: (value, []))
    retrieval_query, retrieval_anchors = contextual(query, conversation_history)
    resolve_home = getattr(
        base,
        "_resolve_hermes_home",
        lambda explicit: explicit or Path(os.getenv("HERMES_HOME", str(Path.home() / ".hermes"))),
    )
    home = resolve_home(hermes_home)
    teleo_kb = home / "bin" / "teleo-kb"
    query_sha256 = hashlib.sha256(query.encode("utf-8")).hexdigest()
    base_record: dict[str, Any] = {
        "generated_at_utc": datetime.now(timezone.utc).isoformat(),
        "event": "pre_llm_call",
        "query_sha256": query_sha256,
        "retrieval_query_sha256": hashlib.sha256(retrieval_query.encode("utf-8")).hexdigest(),
        "retrieval_anchor_count": len(retrieval_anchors),
        "retrieval_anchors_sha256": hashlib.sha256(
            json.dumps(retrieval_anchors, sort_keys=True, separators=(",", ":")).encode("utf-8")
        ).hexdigest(),
        "source": "teleo-kb context --include-excerpts",
    }
    if not teleo_kb.is_file() or not os.access(teleo_kb, os.X_OK):
        record = base_record | {"status": "error", "error": "teleo_kb_missing", "injected": True}
        base._trace(record)
        return base._error_snapshot(query, query_sha256, "teleo_kb_missing")

    timeout = int(os.getenv("LEO_DB_CONTEXT_TIMEOUT_SECONDS", str(base.DEFAULT_TIMEOUT_SECONDS)))
    command = [
        str(teleo_kb),
        "context",
        query,
        "--retrieval-query",
        retrieval_query,
    ]
    for anchor in retrieval_anchors:
        command.extend(("--retrieval-anchor", anchor))
    command.extend(
        [
            "--limit",
            str(base.CONTEXT_CLAIM_LIMIT),
            "--context-limit",
            str(base.CONTEXT_ROW_LIMIT),
            "--include-excerpts",
            "--format",
            "json",
        ]
    )
    try:
        completed = runner(command, capture_output=True, text=True, timeout=timeout, check=False)
    except subprocess.TimeoutExpired:
        record = base_record | {"status": "error", "error": "timeout", "injected": True}
        base._trace(record)
        return base._error_snapshot(query, query_sha256, "timeout")
    except OSError as exc:
        record = base_record | {"status": "error", "error": type(exc).__name__, "injected": True}
        base._trace(record)
        return base._error_snapshot(query, query_sha256, type(exc).__name__)

    if completed.returncode != 0:
        reason = f"teleo_kb_exit_{completed.returncode}"
        record = base_record | {"status": "error", "error": reason, "injected": True}
        base._trace(record)
        return base._error_snapshot(query, query_sha256, reason)

    try:
        payload = json.loads(completed.stdout)
        contracts = payload.get("operational_contracts")
        if not isinstance(contracts, list) or not all(isinstance(item, dict) for item in contracts):
            raise ValueError("operational_contracts_missing")
        claims = payload.get("claims", [])
        if not isinstance(claims, list) or not all(isinstance(item, dict) for item in claims):
            raise ValueError("claims_missing")
        context_rows = payload.get("context_rows", [])
        if not isinstance(context_rows, list) or not all(isinstance(item, dict) for item in context_rows):
            raise ValueError("context_rows_missing")
        compiled_response = payload.get("compiled_response")
        if compiled_response is not None and not isinstance(compiled_response, str):
            raise ValueError("compiled_response_invalid")
        contract_mode = payload.get("runtime_contract_mode")
        if contract_mode not in {"claim_evidence_challenge", "general", "review_only_candidate"}:
            raise ValueError("runtime_contract_mode_invalid")
        if base._requires_database_truth(query) and contract_mode == "general":
            record = base_record | {
                "status": "error",
                "error": "gcp_contract_surface_not_yet_supported",
                "injected": True,
            }
            base._trace(record)
            return base._error_snapshot(query, query_sha256, "gcp_contract_surface_not_yet_supported")
        retrieval_payload, injected_rows_sha256 = base._compact_retrieval_payload(
            claims,
            context_rows,
            payload.get("retrieval_receipt"),
        )
        retrieval_receipt = base._retrieval_receipt_trace(
            payload.get("retrieval_receipt"),
            injected_rows_sha256=injected_rows_sha256,
        )
    except (json.JSONDecodeError, TypeError, ValueError) as exc:
        record = base_record | {"status": "error", "error": str(exc), "injected": True}
        base._trace(record)
        return base._error_snapshot(query, query_sha256, str(exc))

    contract_json = json.dumps(contracts, sort_keys=True, separators=(",", ":"))
    record = base_record | {
        "status": "ok",
        "injected": True,
        "contract_ids": [str(item.get("id") or "") for item in contracts],
        "contract_sha256": hashlib.sha256(contract_json.encode("utf-8")).hexdigest(),
        "compiled_response_available": bool(compiled_response),
        "runtime_contract_mode": contract_mode,
        "database_reasoning_protocol_version": base.DATABASE_REASONING_PROTOCOL_VERSION,
    }
    if retrieval_receipt is not None:
        record["retrieval_receipt"] = retrieval_receipt
    base._trace(record)
    return {
        "status": "ok",
        "query_sha256": query_sha256,
        "contracts": contracts,
        "compiled_response": compiled_response,
        "requires_database_truth": bool({str(item.get("id") or "") for item in contracts} - {"reply_budget"}),
        "database_reasoning_protocol_version": base.DATABASE_REASONING_PROTOCOL_VERSION,
        "context": base._format_context(contracts, retrieval_payload, injected_rows_sha256),
    }


base._load_database_snapshot = _load_database_snapshot


def register(ctx: Any) -> None:
    base.register(ctx)
