from __future__ import annotations

import json
from typing import TYPE_CHECKING

from niannian.mcp.mcp_space import resolve_mcp_memory_space
from niannian.mcp.server.tools.external_helpers import run_inbound_tool

if TYPE_CHECKING:
    from mcp.server.fastmcp import FastMCP

    from niannian.mcp.service import NianNianService


def _external_svc(svc: NianNianService):
    from niannian.external_data.service import ExternalDataService

    memory_store = getattr(getattr(svc, "_nn", None), "_store", None)
    return ExternalDataService(svc.home, config=getattr(svc, "_config", {}), memory_store=memory_store)


def register_external_data_tools(mcp: FastMCP, svc: NianNianService) -> None:
    @mcp.tool()
    def niannian_external_data(envelope_json: str) -> str:
        """外部数据源补丁 v1 — add/delete/overwrite。

        envelope 必填字段：
          operation: add | delete | overwrite
          project: 记忆空间名（英文，如 pose-identification）
          function: 功能目录名（如 habit_corrections）
          payload: 数据体（delete 可省略）
          caller: { mcp_tool, client, client_version, device, session_id }
          occurred_at: ISO8601
          storage_target: cloud（默认，走 L1 三云）| local（写入 local_dir）
          local_dir: storage_target=local 时的根目录
          dedup_key / record_id: 去重或定位

        默认不归 L2 NAS；仅在 Chat 中要求迁移时调用 niannian_external_data_archive。
        """
        data = json.loads(envelope_json)
        project = data.get("project") or ""
        capability_id = str(data.get("capability_id") or "").strip() or None
        space = resolve_mcp_memory_space(svc, project)
        data["project"] = space

        def _apply() -> str:
            home = svc.home
            if home is not None:
                from niannian.memory.space import ensure_memory_space

                ensure_memory_space(home, space)
            result = _external_svc(svc).apply(data)
            return json.dumps(result.to_dict(), ensure_ascii=False)

        return run_inbound_tool(
            svc,
            tool="niannian_external_data",
            args_summary=f"project={space} op={data.get('operation', 'add')}",
            capability_id=capability_id,
            fn=_apply,
        )

    @mcp.tool()
    def niannian_external_data_archive(project: str, function: str, storage_target: str = "cloud", local_dir: str = "") -> str:
        """将外部数据归档到 NAS L2：{memory_space}/{function}/。仅 Chat 明确要求时使用。"""
        space = resolve_mcp_memory_space(svc, project)

        def _archive() -> str:
            home = svc.home
            if home is None:
                raise ValueError("archive requires local NianNian home")
            result = _external_svc(svc).archive_to_l2(
                space,
                function,
                storage_target=storage_target,
                local_dir=local_dir,
            )
            return json.dumps(result, ensure_ascii=False)

        return run_inbound_tool(
            svc,
            tool="niannian_external_data_archive",
            args_summary=f"project={space} function={function}",
            capability_id=None,
            fn=_archive,
        )
