"""消息路由：拿到 inbound JSON 文本后解析 event_type，并 dispatch 到对应 handler。

设计上把 "dispatch" 与 "执行 handler" 分开：
* :meth:`MessageRouter.dispatch` 仅做解析 + 选 handler，**同步**返回 ``True/False``；
* 真正在哪个线程执行由调用方决定（生产路径上是 :class:`AgentThreadMgr` 绑定的 worker，
  测试路径上可以直接同步调用）。
"""

from __future__ import annotations

import json
import logging
from typing import TYPE_CHECKING, Any, Dict, Optional

from ..enums import AgentEventType
from . import handlers

if TYPE_CHECKING:
    from ..agent_sdk import AgentSdk
    from .linksky_client import LinkskyClient


_log = logging.getLogger("linksoul_agentsdk.router")


class MessageRouter:
    """无状态分发器；可被多个 LinkskyClient 共用。"""

    def __init__(self, agent_sdk: "AgentSdk", linksky_client: "LinkskyClient") -> None:
        self._agent_sdk = agent_sdk
        self._linksky_client = linksky_client

    # ----- 给 LinkskyClient 调用：拿到 text 后做一次完整 dispatch -----

    def handle_text(self, text: str) -> bool:
        try:
            msg: Dict[str, Any] = json.loads(text)
        except json.JSONDecodeError:
            _log.warning("invalid json from gw: %s", text[:200])
            return False
        return self.dispatch(msg)

    def dispatch(self, msg: Dict[str, Any]) -> bool:
        event_type = AgentEventType.of(msg.get("type"))
        agent_id = msg.get("agentId") or ""
        robot_cid = msg.get("robotCid") or ""
        event_id = msg.get("eventId") or ""
        if event_type is AgentEventType.ILLEGAL:
            _log.debug("ignore unknown event type=%s", msg.get("type"))
            return False
        agent_sdk = self._agent_sdk
        linksky = self._linksky_client

        if event_type is AgentEventType.AGENTSDK_ROBOT_STATE_SYNC:
            handlers.handle_robot_state_sync(agent_sdk, linksky, agent_id, msg)
        elif event_type is AgentEventType.AGENTSDK_AUDIO_REQUEST_START:
            handlers.handle_audio_request_start(agent_sdk, linksky, agent_id, robot_cid, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_AUDIO_REQUEST_APPEND:
            handlers.handle_audio_request_append(agent_sdk, agent_id, event_id, None, msg)
        elif event_type is AgentEventType.AGENTSDK_AUDIO_REQUEST_COMMIT:
            handlers.handle_audio_request_commit(agent_sdk, linksky, agent_id, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_ASR_REQUEST_TEXT:
            handlers.handle_asr_request_text(agent_sdk, linksky, agent_id, robot_cid, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_VIDEO_H264_REQUEST_APPEND:
            handlers.handle_video_h264_request_append(agent_sdk, linksky, agent_id, event_id, robot_cid, msg)
        elif event_type is AgentEventType.AGENTSDK_VIDEO_IMAGE_REQUEST_APPEND:
            handlers.handle_video_image_request_append(agent_sdk, linksky, agent_id, event_id, robot_cid, msg)
        elif event_type is AgentEventType.AGENTSDK_STATE_REQUEST_META:
            handlers.handle_state_request_meta(agent_sdk, agent_id, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_GREET_REQUEST_SIGNAL:
            handlers.handle_greet_request_signal(agent_sdk, linksky, agent_id, robot_cid, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_GREET_REQUEST_FACE:
            handlers.handle_greet_request_face(agent_sdk, agent_id, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_GREET_REQUEST_VIDEO:
            handlers.handle_greet_request_video(agent_sdk, agent_id, event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_START_REQUEST_ACK:
            handlers.handle_flow_start_request_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_START_EXECUTE_ACK:
            handlers.handle_flow_start_execute_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_TASK_REQUEST_ACK:
            handlers.handle_flow_task_request_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_TASK_EXECUTE_ACK:
            handlers.handle_flow_task_execute_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_END_REQUEST_ACK:
            handlers.handle_flow_end_request_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        elif event_type is AgentEventType.AGENTSDK_FLOW_INTERRUPT_REQUEST_ACK:
            handlers.handle_flow_interrupt_request_ack(agent_sdk, agent_id, msg.get("flowId", ""), event_id, msg)
        else:
            _log.debug("ignore event type=%s", event_type)
            return False
        return True
