#!/usr/bin/env python3
"""Run A_Memorix runtime self-check against real embedding/runtime configuration."""

from __future__ import annotations

import argparse
import asyncio
import json
import sys
import tempfile
from pathlib import Path
from typing import Any

import tomlkit

from _bootstrap import DEFAULT_CONFIG_PATH, DEFAULT_DATA_DIR, resolve_repo_path


def _build_arg_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="A_Memorix runtime self-check")
    parser.add_argument(
        "--config",
        default=str(DEFAULT_CONFIG_PATH),
        help="config.toml path (default: config/a_memorix.toml)",
    )
    parser.add_argument(
        "--data-dir",
        default="",
        help="optional data dir override; default resolved from config.storage.data_dir",
    )
    parser.add_argument(
        "--use-config-data-dir",
        action="store_true",
        help="use config.storage.data_dir directly instead of an isolated temp dir",
    )
    parser.add_argument(
        "--sample-text",
        default="A_Memorix runtime self check",
        help="sample text used for real embedding probe",
    )
    parser.add_argument("--json", action="store_true", help="print JSON report")
    return parser


if any(arg in {"-h", "--help"} for arg in sys.argv[1:]):
    _build_arg_parser().print_help()
    raise SystemExit(0)

from A_memorix.core.runtime.lifecycle_orchestrator import initialize_storage_async
from A_memorix.core.utils.runtime_self_check import run_embedding_runtime_self_check


def _load_config(path: Path) -> dict[str, Any]:
    with open(path, "r", encoding="utf-8") as f:
        raw = tomlkit.load(f)
    return dict(raw) if isinstance(raw, dict) else {}


def _nested_get(config: dict[str, Any], key: str, default: Any = None) -> Any:
    current: Any = config
    for part in key.split("."):
        if isinstance(current, dict) and part in current:
            current = current[part]
        else:
            return default
    return current


class _PluginStub:
    def __init__(self, config: dict[str, Any]):
        self.config = config
        self.vector_store = None
        self.graph_store = None
        self.metadata_store = None
        self.embedding_manager = None
        self.sparse_index = None
        self.relation_write_service = None

    def get_config(self, key: str, default: Any = None) -> Any:
        return _nested_get(self.config, key, default)


async def _main_async(args: argparse.Namespace) -> int:
    config_path = resolve_repo_path(args.config, fallback=DEFAULT_CONFIG_PATH)
    if not config_path.exists():
        print(f"❌ 配置文件不存在: {config_path}")
        return 2

    config = _load_config(config_path)
    temp_dir_ctx = None
    if args.data_dir:
        storage_dir = str(resolve_repo_path(args.data_dir, fallback=DEFAULT_DATA_DIR))
    elif args.use_config_data_dir:
        raw_data_dir = str(_nested_get(config, "storage.data_dir", "./data") or "./data").strip()
        storage_dir = str(resolve_repo_path(raw_data_dir, fallback=DEFAULT_DATA_DIR))
    else:
        temp_dir_ctx = tempfile.TemporaryDirectory(prefix="memorix-runtime-self-check-")
        storage_dir = temp_dir_ctx.name

    storage_cfg = config.setdefault("storage", {})
    storage_cfg["data_dir"] = storage_dir

    plugin = _PluginStub(config)
    try:
        await initialize_storage_async(plugin)
        report = await run_embedding_runtime_self_check(
            config=config,
            vector_store=plugin.vector_store,
            embedding_manager=plugin.embedding_manager,
            sample_text=str(args.sample_text or "A_Memorix runtime self check"),
        )
        report["data_dir"] = storage_dir
        report["isolated_data_dir"] = temp_dir_ctx is not None
        if args.json:
            print(json.dumps(report, ensure_ascii=False, indent=2))
        else:
            print("A_Memorix Runtime Self-Check")
            print(f"ok: {report.get('ok')}")
            print(f"code: {report.get('code')}")
            print(f"message: {report.get('message')}")
            print(f"configured_dimension: {report.get('configured_dimension')}")
            print(f"vector_store_dimension: {report.get('vector_store_dimension')}")
            print(f"detected_dimension: {report.get('detected_dimension')}")
            print(f"encoded_dimension: {report.get('encoded_dimension')}")
            print(f"elapsed_ms: {float(report.get('elapsed_ms', 0.0)):.2f}")
        return 0 if bool(report.get("ok")) else 1
    finally:
        if plugin.metadata_store is not None:
            try:
                plugin.metadata_store.close()
            except Exception:
                pass
        if temp_dir_ctx is not None:
            temp_dir_ctx.cleanup()


def main() -> int:
    parser = _build_arg_parser()
    args = parser.parse_args()
    return asyncio.run(_main_async(args))


if __name__ == "__main__":
    raise SystemExit(main())
