"""ACP device/* method handlers.

Handles device management commands: info, screenshot, ui-tree, action,
install, and shell. Each method delegates to the DeviceRuntime.
"""

from __future__ import annotations

import base64
import logging
from dataclasses import asdict
from typing import Any

from ..runtime.base import DeviceRuntime

logger = logging.getLogger(__name__)


class DeviceHandler:
    """Handles ACP ``device/*`` JSON-RPC methods."""

    def __init__(self, runtime: DeviceRuntime) -> None:
        self._runtime = runtime

    async def handle_info(self, msg: dict[str, Any]) -> dict[str, Any]:
        info = await self._runtime.get_info()
        d = asdict(info)
        d["type"] = info.type.value
        d["capabilities"] = [c.value for c in info.capabilities]
        return d

    async def handle_screenshot(self, msg: dict[str, Any]) -> dict[str, Any]:
        png_bytes = await self._runtime.screenshot()
        return {
            "image": base64.b64encode(png_bytes).decode(),
            "format": "png",
        }

    async def handle_ui_tree(self, msg: dict[str, Any]) -> dict[str, Any]:
        nodes = await self._runtime.get_ui_tree()
        return {"nodes": nodes}

    async def handle_action(self, msg: dict[str, Any]) -> dict[str, Any]:
        params = msg.get("params", {})
        action = params.get("action", "")

        if action == "tap":
            x, y = params.get("x", 0), params.get("y", 0)
            await self._runtime.tap(x, y)
        elif action == "long_press":
            x, y = params.get("x", 0), params.get("y", 0)
            await self._runtime.long_press(x, y, params.get("duration_ms", 1000))
        elif action == "swipe":
            await self._runtime.swipe(
                params.get("x1", 0), params.get("y1", 0),
                params.get("x2", 0), params.get("y2", 0),
                params.get("duration_ms", 300),
            )
        elif action == "type":
            text = params.get("text", "")
            if not text:
                raise ValueError("'text' is required for action 'type'")
            await self._runtime.type_text(text)
        elif action == "press_key":
            keycode = params.get("keycode", "")
            if not keycode:
                raise ValueError("'keycode' is required for action 'press_key'")
            await self._runtime.press_key(keycode)
        elif action == "open_app":
            package = params.get("package", "")
            if not package:
                raise ValueError("'package' is required for action 'open_app'")
            await self._runtime.open_app(package)
        else:
            raise ValueError(f"Unknown action: {action}")

        return {"status": "ok", "action": action}

    async def handle_install(self, msg: dict[str, Any]) -> dict[str, Any]:
        params = msg.get("params", {})
        apk_path = params.get("apk_path", "")
        if not apk_path:
            raise ValueError("apk_path is required")
        await self._runtime.install_app(apk_path)
        return {"status": "ok"}

    async def handle_shell(self, msg: dict[str, Any]) -> dict[str, Any]:
        params = msg.get("params", {})
        command = params.get("command", "")
        if not command:
            raise ValueError("command is required")
        output = await self._runtime.execute_shell(command)
        return {"output": output}
