"""
Agent Messages — send and read messages via orch-hq feed.

Usage from within an agent:

    from orchagent import message

    # Send a simple message
    message.send("Daily Brief", "Here's what's happening today...")

    # Send with level
    message.send("Deployment Failed", "Build error on main", level="error")

    # Send with metadata
    message.send("Report Ready", body, level="success", metadata={"report_url": "..."})

    # Read messages (e.g. check what other agents have reported)
    msgs = message.list(limit=10)
    errors = message.list(level="error", limit=5)
    briefs = message.list(agent_name="morning-brief", limit=1)

Messages appear in the orch-hq desktop app Messages panel. They are distinct
from regular run output — only messages the agent author explicitly sends
via this API are surfaced in the Messages feed.

All functions are synchronous (blocking) for simplicity in agent scripts.
"""

from __future__ import annotations

import os
from typing import Any, Optional

import httpx

_DEFAULT_GATEWAY_URL = "https://api.orchagent.io"
_DEFAULT_TIMEOUT = 30.0


class MessageError(Exception):
    """Failed to send a message."""
    def __init__(self, message: str, status_code: int | None = None):
        super().__init__(message)
        self.status_code = status_code


def _get_client() -> tuple[httpx.Client, dict[str, str]]:
    """Get HTTP client and auth headers."""
    gateway_url = os.environ.get("ORCHAGENT_GATEWAY_URL", _DEFAULT_GATEWAY_URL)
    api_key = os.environ.get("ORCHAGENT_SERVICE_KEY") or os.environ.get("ORCHAGENT_API_KEY", "")

    headers = {"Authorization": f"Bearer {api_key}"}

    # Propagate orchestration headers if present
    for env_key, header_name in [
        ("ORCHAGENT_CALL_CHAIN", "x-orchagent-call-chain"),
        ("ORCHAGENT_BILLING_ORG_ID", "x-orchagent-billing-org-id"),
        ("ORCHAGENT_REQUEST_ID", "x-orchagent-request-id"),
    ]:
        val = os.environ.get(env_key)
        if val:
            headers[header_name] = val

    client = httpx.Client(base_url=gateway_url, timeout=_DEFAULT_TIMEOUT)
    return client, headers


def send(
    title: str,
    body: str,
    *,
    level: str = "info",
    agent_name: Optional[str] = None,
    metadata: Optional[dict[str, Any]] = None,
) -> dict:
    """
    Send a message to the orch-hq feed.

    Args:
        title: Short title / subject line
        body: Message content (plain text or markdown)
        level: "info" | "success" | "warning" | "error" (default: "info")
        agent_name: Override agent name (auto-detected if omitted)
        metadata: Optional extra data to attach

    Returns:
        dict with id, agent_name, title, level, created_at

    Raises:
        MessageError: If the send fails
    """
    client, headers = _get_client()

    payload: dict[str, Any] = {
        "title": title,
        "body": body,
        "level": level,
    }
    if agent_name:
        payload["agent_name"] = agent_name
    if metadata:
        payload["metadata"] = metadata

    try:
        response = client.post("/messages", json=payload, headers=headers)
    except httpx.HTTPError as e:
        raise MessageError(f"HTTP error: {e}") from e
    finally:
        client.close()

    if response.status_code == 201:
        return response.json()

    # Error
    try:
        err = response.json()
        msg = err.get("message", response.text)
    except Exception:
        msg = response.text

    raise MessageError(f"Failed to send message: {msg}", status_code=response.status_code)


def list(
    *,
    limit: int = 50,
    offset: int = 0,
    level: Optional[str] = None,
    agent_name: Optional[str] = None,
) -> list[dict]:
    """
    List messages from the orch-hq feed.

    Useful for agents that need to check what other agents have reported —
    e.g. a morning brief agent reading overnight error messages.

    Args:
        limit: Max messages to return (1-200, default 50)
        offset: Pagination offset (default 0)
        level: Filter by level — "info" | "success" | "warning" | "error"
        agent_name: Filter by agent name

    Returns:
        List of message dicts, each with: id, agent_name, title, body,
        level, metadata, created_at

    Raises:
        MessageError: If the request fails
    """
    client, headers = _get_client()

    params: dict[str, Any] = {"limit": limit, "offset": offset}
    if level:
        params["level"] = level
    if agent_name:
        params["agent_name"] = agent_name

    try:
        response = client.get("/messages", params=params, headers=headers)
    except httpx.HTTPError as e:
        raise MessageError(f"HTTP error: {e}") from e
    finally:
        client.close()

    if response.status_code == 200:
        data = response.json()
        return data.get("messages", [])

    try:
        err = response.json()
        msg = err.get("message", response.text)
    except Exception:
        msg = response.text

    raise MessageError(f"Failed to list messages: {msg}", status_code=response.status_code)
