"""
Discord Bridge — Forward broker messages to a Discord webhook.

Sends broker channel messages as Discord embeds so cross-terminal chatter
is visible on mobile.  Uses only stdlib (urllib, json).  All functions sync.

Configuration:
  1. Env var BROKER_DISCORD_WEBHOOK  (preferred)
  2. Fallback: state/broker/config.json  {"discord_webhook": "https://..."}

If neither is set, bridging is silently disabled.

Rate limit: max 5 messages per 10-second window (Discord allows 30/min).
"""

import json
import os
import time
import urllib.error
import urllib.request
from pathlib import Path
from typing import Optional

# ── Paths ─────────────────────────────────────────────────────────────────

PROJECT_ROOT = Path(__file__).resolve().parents[2]
BROKER_DIR = Path(os.environ.get("BROKER_DIR", PROJECT_ROOT / "state" / "broker"))
CONFIG_PATH = BROKER_DIR / "config.json"

# ── Embed Colors ──────────────────────────────────────────────────────────

_COLORS = {
    "info":       0x3498DB,   # blue
    "alert":      0xE74C3C,   # red
    "request":    0xE67E22,   # orange
    "file_ready": 0x2ECC71,  # green
    "status":     0x95A5A6,   # gray
}
_DEFAULT_COLOR = 0x95A5A6     # gray for unknown msg_type

# ── Rate Limiter ──────────────────────────────────────────────────────────

_WINDOW_SECONDS = 10
_MAX_PER_WINDOW = 5
_send_times: list[float] = []


def _rate_limited() -> bool:
    """Return True if we've hit the per-window send cap."""
    now = time.monotonic()
    cutoff = now - _WINDOW_SECONDS
    # Prune old entries
    while _send_times and _send_times[0] < cutoff:
        _send_times.pop(0)
    return len(_send_times) >= _MAX_PER_WINDOW


def _record_send() -> None:
    """Record a successful send for rate-limit tracking."""
    _send_times.append(time.monotonic())


# ── Webhook Resolution ────────────────────────────────────────────────────


def get_webhook() -> Optional[str]:
    """Get the current Discord webhook URL.

    Checks (in order):
      1. BROKER_DISCORD_WEBHOOK environment variable
      2. state/broker/config.json  {"discord_webhook": "..."}

    Returns the URL string, or None if not configured.
    """
    url = os.environ.get("BROKER_DISCORD_WEBHOOK")
    if url:
        return url

    try:
        data = json.loads(CONFIG_PATH.read_text("utf-8"))
        return data.get("discord_webhook") or None
    except (FileNotFoundError, json.JSONDecodeError, OSError):
        return None


def set_webhook(url: str) -> None:
    """Save a Discord webhook URL to state/broker/config.json.

    Merges with any existing keys in the config file.
    Creates parent directories if needed.
    """
    CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)

    config: dict = {}
    try:
        config = json.loads(CONFIG_PATH.read_text("utf-8"))
    except (FileNotFoundError, json.JSONDecodeError, OSError):
        pass

    config["discord_webhook"] = url
    CONFIG_PATH.write_text(json.dumps(config, indent=2))


def is_enabled() -> bool:
    """Check whether the Discord bridge is active (webhook URL is configured)."""
    return get_webhook() is not None


# ── Core Send ─────────────────────────────────────────────────────────────


def forward_to_discord(entry: dict) -> bool:
    """Forward a broker message entry to Discord as an embed.

    Args:
        entry: Broker message dict with keys:
            channel, message, msg_type, session_name, platform,
            session_id, timestamp.

    Returns:
        True if the message was sent successfully.
        False if bridging is disabled, rate-limited, or the POST failed.
    """
    webhook_url = get_webhook()
    if not webhook_url:
        return False

    if _rate_limited():
        return False

    channel = entry.get("channel", "general")
    message = entry.get("message", "")
    msg_type = entry.get("msg_type", "info")
    session_name = entry.get("session_name", "unknown")
    platform = entry.get("platform", "unknown")
    session_id = entry.get("session_id", "")
    timestamp = entry.get("timestamp", "")

    color = _COLORS.get(msg_type, _DEFAULT_COLOR)

    payload = {
        "embeds": [{
            "title": f"#{channel}",
            "description": message,
            "color": color,
            "author": {"name": f"{session_name}@{platform}"},
            "timestamp": timestamp,
            "footer": {"text": f"{msg_type} | {session_id}"},
        }]
    }

    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(
        webhook_url,
        data=data,
        headers={"Content-Type": "application/json"},
        method="POST",
    )

    try:
        urllib.request.urlopen(req, timeout=5)
        _record_send()
        return True
    except (urllib.error.URLError, urllib.error.HTTPError, OSError):
        return False
