"""AgentModule — agent registration, status, and session key management.

Combines REST calls (auth worker) with on-chain calls (AgentController)
for full agent lifecycle management.
"""

from __future__ import annotations

from typing import Dict

from openhedge.models.agent import AgentProfile, AgentRegistration
from openhedge.modules.base import BaseModule


class AgentModule(BaseModule):
    """Interact with the OpenHedge agent registry.

    REST endpoints are backed by the auth Cloudflare Worker.
    On-chain methods interact with the AgentController contract.
    """

    async def register(self, registration: AgentRegistration) -> AgentProfile:
        """Register a new agent wallet with the platform.

        Returns the created :class:`AgentProfile` on success.
        """
        data = await self._api_post("/agents", json_body=registration.model_dump())
        return AgentProfile(**data)

    async def status(self) -> AgentProfile:
        """Retrieve the current agent profile for the authenticated API key."""
        data = await self._api_get("/agents/me")
        return AgentProfile(**data)

    # ------------------------------------------------------------------
    # On-chain: AgentController session key management
    # ------------------------------------------------------------------

    async def issue_session_key(
        self,
        vault: str,
        session_key: str,
        duration_seconds: int,
        max_trade_size: int,
    ) -> dict:
        """Issue a scoped session key for automated trading.

        Parameters
        ----------
        vault:
            Vault address the session key is scoped to.
        session_key:
            Address of the session key wallet.
        duration_seconds:
            Duration in seconds before the key expires.
        max_trade_size:
            Maximum trade size allowed per transaction.

        Returns
        -------
        Dict with ``tx_hash`` and ``key_id``.
        """
        # AgentController.issueSessionKey(address vault, address sessionKey,
        #     uint256 duration, uint256 maxTradeSize)
        calldata = self._encode_call(
            "issueSessionKey(address,address,uint256,uint256)",
            ["address", "address", "uint256", "uint256"],
            [vault, session_key, duration_seconds, max_trade_size],
        )

        agent_controller = self._contracts["agent_controller"]
        receipt = await self._send_tx(to=agent_controller, data=calldata)

        # Parse SessionKeyIssued event to extract keyId
        # SessionKeyIssued(address indexed vault, address indexed sessionKey,
        #     bytes32 indexed keyId, uint256 expiresAt, uint256 maxTradeSize)
        key_id = "0x" + "00" * 32  # fallback
        for log in receipt.get("logs", []):
            topics = log.get("topics", [])
            if len(topics) >= 4:
                key_id = topics[3]
                break

        return {
            "tx_hash": receipt.get("transactionHash", ""),
            "key_id": key_id,
        }

    async def revoke_session_key(self, key_id: str) -> str:
        """Revoke an existing session key.

        Parameters
        ----------
        key_id:
            The bytes32 key ID to revoke.

        Returns
        -------
        Transaction hash.
        """
        # AgentController.revokeSessionKey(bytes32 keyId)
        calldata = self._encode_call(
            "revokeSessionKey(bytes32)",
            ["bytes32"],
            [bytes.fromhex(key_id[2:]) if key_id.startswith("0x") else bytes.fromhex(key_id)],
        )

        agent_controller = self._contracts["agent_controller"]
        receipt = await self._send_tx(to=agent_controller, data=calldata)

        return receipt.get("transactionHash", "")
