"""
agentpaas.services.event_bus — System event bus

Manages event subscriptions. Agents subscribe to system/file/git events
and bind auto-actions. Actual event detection is done by platform daemon.
"""
from __future__ import annotations

import json
import os
import time
from dataclasses import dataclass, field, asdict
from typing import Any, Dict, List, Optional


@dataclass
class EventSubscription:
    id: str = ""
    agent_id: str = ""
    event_pattern: str = ""     # e.g. "system.file.created:~/Desktop/*"
    action: str = "auto_run"    # auto_run / notify / log
    input_template: str = ""    # e.g. "检测到新文件: {event_data}"
    enabled: bool = True
    created_at: float = 0
    trigger_count: int = 0

    def __post_init__(self):
        if not self.id:
            import uuid
            self.id = f"evt_{uuid.uuid4().hex[:8]}"
        if self.created_at == 0:
            self.created_at = time.time()

    def matches(self, event_type: str) -> bool:
        """Check if this subscription matches an event."""
        pattern = self.event_pattern.split(":")[0]
        return event_type.startswith(pattern) or pattern == "*"


@dataclass
class Event:
    type: str                   # e.g. "system.file.created"
    data: Dict[str, Any] = field(default_factory=dict)
    timestamp: float = 0
    source: str = ""

    def __post_init__(self):
        if self.timestamp == 0:
            self.timestamp = time.time()


EVENTS_PATH = os.path.expanduser("~/.lambdagent/events.json")


class EventBus:
    """Event subscription manager."""

    def __init__(self, path: str = ""):
        self.path = path or EVENTS_PATH
        self._subscriptions: Dict[str, EventSubscription] = {}
        self._history: List[Event] = []
        self._load()

    def subscribe(self, event_pattern: str, agent_id: str = "",
                  action: str = "notify", input_template: str = "") -> EventSubscription:
        sub = EventSubscription(
            agent_id=agent_id, event_pattern=event_pattern,
            action=action, input_template=input_template,
        )
        self._subscriptions[sub.id] = sub
        self._save()
        return sub

    def unsubscribe(self, sub_id: str) -> bool:
        if sub_id in self._subscriptions:
            del self._subscriptions[sub_id]
            self._save()
            return True
        return False

    def publish(self, event_type: str, data: Dict = None, source: str = "") -> List[EventSubscription]:
        """Publish an event, return matching subscriptions."""
        event = Event(type=event_type, data=data or {}, source=source)
        self._history.append(event)
        if len(self._history) > 200:
            self._history = self._history[-200:]

        matched = []
        for sub in self._subscriptions.values():
            if sub.enabled and sub.matches(event_type):
                sub.trigger_count += 1
                matched.append(sub)
        self._save()
        return matched

    def list_subscriptions(self) -> List[EventSubscription]:
        return list(self._subscriptions.values())

    def history(self, limit: int = 20) -> List[Event]:
        return self._history[-limit:]

    def _save(self):
        os.makedirs(os.path.dirname(self.path), exist_ok=True)
        data = {
            "subscriptions": {k: asdict(v) for k, v in self._subscriptions.items()},
        }
        with open(self.path, "w") as f:
            json.dump(data, f, indent=2)

    def _load(self):
        if not os.path.exists(self.path):
            return
        try:
            with open(self.path) as f:
                data = json.load(f)
            for k, v in data.get("subscriptions", {}).items():
                self._subscriptions[k] = EventSubscription(
                    **{key: val for key, val in v.items() if key in EventSubscription.__dataclass_fields__}
                )
        except Exception:
            pass


# Agent-side tool functions
_default_bus = None

def _get_bus() -> EventBus:
    global _default_bus
    if _default_bus is None:
        _default_bus = EventBus()
    return _default_bus


def event_subscribe(input_val: Any) -> str:
    params = _parse(input_val)
    pattern = params.get("event", params.get("pattern", ""))
    if not pattern:
        return "[ERROR] event pattern is required (e.g. 'system.file.created:~/Desktop/*')"
    sub = _get_bus().subscribe(
        event_pattern=pattern,
        action=params.get("action", "notify"),
        input_template=params.get("template", ""),
    )
    return f"[OK] Subscribed: {sub.id} → {pattern} ({sub.action})"


def event_list(input_val: Any) -> str:
    subs = _get_bus().list_subscriptions()
    if not subs:
        return "[EMPTY] No event subscriptions"
    lines = ["Event subscriptions:"]
    for s in subs:
        status = "✅" if s.enabled else "⏸"
        lines.append(f"  {status} {s.id}: {s.event_pattern} → {s.action} (triggered {s.trigger_count}x)")
    return "\n".join(lines)


def _parse(input_val: Any) -> dict:
    if isinstance(input_val, dict):
        return input_val
    if isinstance(input_val, str):
        try:
            return json.loads(input_val)
        except Exception:
            return {"event": input_val}
    return {}
