"""Webhook hooks and transient system_event routes for [mugi_backend._build_app](mugi_backend.py)."""
from __future__ import annotations

import asyncio
from typing import Any

from fastapi import Request as FRequest
from fastapi.responses import JSONResponse

from activity_bus import emit_activity_enriched
from persistence import generate_secure_token
from run_context import clear_run_context, sanitize_run_id, set_run_context
from utils.sliding_window_rate_limiter import SlidingWindowRateLimiter


def register_hooks_routes(fastapi_app: Any, *, delegate: Any) -> None:
    hooks_limiter = SlidingWindowRateLimiter(max_calls=10, window_seconds=60.0)
    system_event_limiter = SlidingWindowRateLimiter(max_calls=10, window_seconds=60.0)

    @fastapi_app.post("/hooks/wake")
    async def hooks_wake(request: FRequest):
        body = await request.json()
        text = (body.get("text") or "").strip()
        if not text:
            return JSONResponse(content={"error": "text required"}, status_code=400)
        if len(text) > 10000:
            return JSONResponse(content={"error": "text too long (max 10000 chars)"}, status_code=400)
        thread_id = delegate._current_thread_id
        trigger_turn = bool(body.get("trigger_turn", False))
        hook_run_id = sanitize_run_id(generate_secure_token(6))

        if not hooks_limiter.allow():
            return JSONResponse(content={"error": "rate limit exceeded"}, status_code=429)

        from chat_storage import append_messages

        append_messages(thread_id, [{"role": "user", "content": f"[System Event] {text}"}])

        try:
            emit_activity_enriched({
                "source": "hooks", "state": "info",
                "summary": f"Wake hook: {text[:80]}",
                "thread_id": thread_id,
                "run_id": hook_run_id,
            })
        except Exception:
            pass
        delegate._push_event({"type": "messages_reload"}, thread_id)

        if trigger_turn:
            from chat_storage import get_messages

            recent = get_messages(thread_id)[-10:]
            context = "\n".join(
                f"{m['role']}: {str(m.get('content',''))[:200]}" for m in recent
                if m.get("role") in ("user", "assistant")
            )
            from subagent_runner import run_subagent
            from tool_policy import context_from_prefs_and_flags

            _hooks_policy_ctx = context_from_prefs_and_flags(unattended_external=True, hooks_triggered=True, subagent_mode=True)

            def _run_hook_turn():
                _token = set_run_context(run_id=hook_run_id, thread_id=thread_id)
                try:
                    return run_subagent(
                        task_description=f"System event: {text}\n\nRespond based on this context.",
                        agent_type="hooks",
                        context_snippet=context,
                        timeout_seconds=60,
                        policy_context=_hooks_policy_ctx,
                    )
                finally:
                    clear_run_context(_token)

            result = await asyncio.get_event_loop().run_in_executor(None, _run_hook_turn)
            append_messages(thread_id, [{"role": "assistant", "content": result}])
            delegate._push_event({"type": "messages_reload"}, thread_id)

        return JSONResponse(content={"ok": True, "thread_id": thread_id})

    @fastapi_app.post("/system_event")
    async def post_system_event(request: FRequest):
        if not system_event_limiter.allow():
            return JSONResponse(content={"error": "rate limit exceeded"},
                                status_code=429)
        body = await request.json()
        text = (body.get("text") or "").strip()
        text = "".join(ch for ch in text if ch.isprintable() or ch in ("\n", "\t")).strip()
        source = (body.get("source") or "system").strip()[:50]
        if not text:
            return JSONResponse(content={"error": "text required"},
                                status_code=400)
        if len(text) > 500:
            return JSONResponse(
                content={"error": "text too long (max 500 chars)"},
                status_code=400)
        tid = ((body.get("thread_id") or "").strip()
               or delegate._current_thread_id)
        delegate._push_event(
            {"type": "system_event", "text": text, "source": source}, tid)
        return JSONResponse(content={"ok": True})

    @fastapi_app.post("/hooks/agent")
    async def hooks_agent(request: FRequest):
        body = await request.json()
        prompt = (body.get("prompt") or "").strip()
        if not prompt:
            return JSONResponse(content={"error": "prompt required"}, status_code=400)
        if len(prompt) > 10000:
            return JSONResponse(content={"error": "prompt too long (max 10000 chars)"}, status_code=400)
        if not hooks_limiter.allow():
            return JSONResponse(content={"error": "rate limit exceeded"}, status_code=429)
        agent_type = body.get("agent_type", "hooks")
        if agent_type != "hooks":
            try:
                from core.config import get_config

                cfg = get_config()
                if not (cfg.get("hooks") or {}).get("allow_custom_profile", False):
                    agent_type = "hooks"
            except Exception:
                agent_type = "hooks"
        try:
            from subagent_runner import run_subagent
            from tool_policy import context_from_prefs_and_flags

            _hooks_policy_ctx = context_from_prefs_and_flags(unattended_external=True, hooks_triggered=True, subagent_mode=True)
            hook_run_id = sanitize_run_id(generate_secure_token(6))

            def _run_hook_agent():
                _token = set_run_context(run_id=hook_run_id)
                try:
                    return run_subagent(
                        task_description=prompt,
                        agent_type=agent_type,
                        timeout_seconds=60,
                        policy_context=_hooks_policy_ctx,
                    )
                finally:
                    clear_run_context(_token)

            result = await asyncio.get_event_loop().run_in_executor(None, _run_hook_agent)
            return JSONResponse(content={"ok": True, "result": result})
        except TimeoutError:
            return JSONResponse(content={"error": "agent timed out"}, status_code=503)
        except Exception as e:
            return JSONResponse(content={"error": str(e)[:200]}, status_code=500)
