from __future__ import annotations

from pathlib import Path
from typing import Any

from aicd.env_probe import (
    build_environment_digest,
    capabilities_summary_path,
    load_runtime_env_snapshot,
    refresh_runtime_env_file,
    runtime_env_path,
    summarize_commands,
)
from aicd.network_policy import aicd_runtime_flags_from_config
from aicd.tools.session_logs_tool import list_session_logs, read_session_log_tail


def _runtime_env_refresh(router: Any, args: dict[str, Any]) -> dict[str, Any]:
    del args  # 无参数；保留以兼容 OpenAI tools schema
    path, data = refresh_runtime_env_file(
        router._layout, aicd_runtime=aicd_runtime_flags_from_config(router._cfg)
    )
    router.notify_env_capabilities_updated(data, path)
    avail, total = summarize_commands(data)
    return {
        "ok": True,
        "path": str(path),
        "capabilities_summary_path": str(capabilities_summary_path(router._layout)),
        "generated_at": data.get("generated_at"),
        "commands_available": avail,
        "commands_total": total,
        "hint": "Use fs_read_file on path for full YAML; capabilities_summary_path mirrors the model-facing "
        "snapshot; call again after user installs tools.",
    }


def _agent_environment_digest(router: Any, args: dict[str, Any]) -> dict[str, Any]:
    layout = router._layout
    cfg = router._cfg
    refresh_first = bool(args.get("refresh_first", False))
    if refresh_first:
        path, data = refresh_runtime_env_file(
            layout, aicd_runtime=aicd_runtime_flags_from_config(cfg)
        )
        router.notify_env_capabilities_updated(data, path)
    else:
        data = load_runtime_env_snapshot(layout)
    yp = str(runtime_env_path(layout).resolve())
    cap_p = str(capabilities_summary_path(layout).resolve())
    ai_out, ai_tmp = router.get_ai_paths()
    digest = build_environment_digest(
        data,
        ai_workspace_cwd=str(router.cwd.resolve()),
        ai_output_root=str(ai_out),
        ai_tmp_dir=str(ai_tmp),
        runtime_yaml_path=yp,
        capabilities_summary_path_str=cap_p,
        agent_max_tool_rounds=int(cfg.agent.max_tool_rounds),
        sub_agent_max_tool_rounds=int(cfg.agent.sub_agent_max_tool_rounds),
        llm_proto=str(cfg.llm.proto),
        llm_model=str(cfg.llm.model),
        llm_api_key_configured=bool(str(cfg.llm.api_key or "").strip()),
        aicd_home=str(layout["root"].resolve()),
        aicd_session_logs_dir=str(layout["logs"].resolve()),
    )
    avail, total = summarize_commands(data)
    active_sid: str | None = None
    sid_path = layout["data"] / "active_chat_session_id.txt"
    if sid_path.is_file():
        try:
            t = sid_path.read_text(encoding="utf-8").strip()
            if t:
                active_sid = t
        except OSError:
            active_sid = None
    out: dict[str, Any] = {
        "ok": True,
        "generated_at": data.get("generated_at"),
        "commands_available": avail,
        "commands_total": total,
        **digest,
    }
    if active_sid is not None:
        out["active_chat_session_id"] = active_sid
    if args.get("include_capabilities_text"):
        cap = capabilities_summary_path(layout)
        mc = int(args.get("capabilities_max_chars", 6000) or 6000)
        mc = max(500, min(12000, mc))
        if cap.is_file():
            txt = cap.read_text(encoding="utf-8", errors="replace")
            out["capabilities_summary_excerpt"] = txt[:mc]
        else:
            out["capabilities_summary_excerpt"] = ""
    return out


def _aicd_session_logs(router: Any, args: dict[str, Any]) -> dict[str, Any]:
    logs_dir = router._layout["logs"]
    op = str(args.get("op") or "list").strip().lower()
    slog = getattr(router, "_session_log", None)
    current_path = slog.path if slog is not None else None
    if op == "list":
        return list_session_logs(
            logs_dir,
            limit=int(args.get("limit", 30)),
            current_process_log=current_path,
        )
    if op == "read_tail":
        explicit: Path | None = None
        if bool(args.get("this_process", False)):
            if current_path is None:
                return {
                    "ok": False,
                    "error": "this_process requested but session log is not available on this router",
                }
            explicit = current_path
        lco = args.get("line_contains")
        lrx = args.get("line_regex")
        return read_session_log_tail(
            logs_dir,
            explicit_path=explicit,
            filename=args.get("filename"),
            latest=bool(args.get("latest", False)) if explicit is None else False,
            max_lines=int(args.get("max_lines", 200)),
            max_bytes=int(args.get("max_bytes", 120_000)),
            line_contains=lco if isinstance(lco, str) else None,
            line_regex=lrx if isinstance(lrx, str) else None,
        )
    return {
        "ok": False,
        "error": "op must be list or read_tail",
        "hint": "list: limit; read_tail: this_process, latest, filename, line_contains/line_regex, max_lines, max_bytes",
    }


HANDLERS: dict[str, Any] = {
    "runtime_env_refresh": _runtime_env_refresh,
    "agent_environment_digest": _agent_environment_digest,
    "aicd_session_logs": _aicd_session_logs,
}
