#!/usr/bin/env python3
"""Standalone door controller agent for OmniLink.

This script demonstrates how to create an OmniLink agent that registers
two commands — ``open_door`` and ``close_door`` — and serves them over
the HTTP bridge. It can also be run directly to test commands locally
without a bridge.

Usage
-----
Run locally (no bridge)::

    python agent.py

Run with the HTTP bridge (listens on port 8080)::

    python agent.py --http

Run with the MQTT bridge (connects to broker at localhost:1883)::

    python agent.py --mqtt

You can also start the agent via the use case loader::

    OmniLink_USE_CASE=omnilink.examples.door_controller.use_case python agent.py --http
"""

from __future__ import annotations

import argparse
import pathlib
import sys
from typing import Any, Dict

# Allow running from the repository without installing the package.
LIB_PATH = pathlib.Path(__file__).resolve().parents[3] / "src"
if str(LIB_PATH) not in sys.path:
    sys.path.insert(0, str(LIB_PATH))

from omnilink import OmniLinkEngine, OmniLinkHTTPBridge, TypeRegistry

from api import close_door, get_summary, open_door


def build_engine() -> OmniLinkEngine:
    """Build the engine with open_door and close_door commands."""

    types = TypeRegistry()
    types.register("door", r"(?:front_door|back_door|garage_door)")

    engine = OmniLinkEngine(
        [
            "open_the_[door:door]",
            "close_the_[door:door]",
        ],
        types=types,
    )

    def handle_open(evt: Dict[str, Any]) -> Dict[str, Any]:
        door = evt["vars"].get("door")
        if not door:
            return {"ack": False, "error": "missing door"}
        result = open_door(door)
        messenger = evt.get("messenger")
        if messenger:
            from omnilink import AgentFeedback
            messenger.send_feedback(
                AgentFeedback(message=f"Opened {result['door']}", kind="success")
            )
        return {"ack": True, "result": result}

    def handle_close(evt: Dict[str, Any]) -> Dict[str, Any]:
        door = evt["vars"].get("door")
        if not door:
            return {"ack": False, "error": "missing door"}
        result = close_door(door)
        messenger = evt.get("messenger")
        if messenger:
            from omnilink import AgentFeedback
            messenger.send_feedback(
                AgentFeedback(message=f"Closed {result['door']}", kind="success")
            )
        return {"ack": True, "result": result}

    engine.on_template("open_the_[door:door]", handle_open)
    engine.on_template("close_the_[door:door]", handle_close)
    return engine


def run_local_demo(engine: OmniLinkEngine) -> None:
    """Exercise both commands locally and print results."""

    print("=== Door Controller Agent — Local Demo ===\n")

    result = engine.handle("open the front_door")
    print(f"open front_door -> {result['result']}")

    result = engine.handle("close the front_door")
    print(f"close front_door -> {result['result']}")

    result = engine.handle("open the garage_door")
    print(f"open garage_door -> {result['result']}")

    print(f"\nDoor summary: {get_summary()}")


def register_on_platform(omni_key: str) -> None:
    """Register this agent as a profile on the OmniLink platform."""

    from omnilink.client import OmniLinkClient

    client = OmniLinkClient(omni_key=omni_key)

    # Check if a profile named "door-controller" already exists
    profiles = client.list_profiles()
    for p in profiles:
        if p.get("name", "").lower() == "door-controller":
            print(f"Profile 'door-controller' already exists (id: {p['id']})")
            return

    profile = client.create_profile(
        "door-controller",
        settings={
            "agentName": "door-controller",
            "availableCommands": "open_door, close_door",
            "mainTask": "You are a door controller agent. When the user asks to open a door, use the open_door command. When the user asks to close a door, use the close_door command.",
        },
    )
    print(f"Created profile 'door-controller' (id: {profile['id']})")


def main() -> None:
    parser = argparse.ArgumentParser(description="OmniLink Door Controller Agent")
    parser.add_argument("--http", action="store_true", help="Start the HTTP bridge")
    parser.add_argument("--mqtt", action="store_true", help="Start the MQTT bridge")
    parser.add_argument("--register", metavar="OMNI_KEY", help="Register this agent on the platform using your Omni Key")
    args = parser.parse_args()

    if args.register:
        register_on_platform(args.register)
        return

    engine = build_engine()

    if args.http:
        bridge = OmniLinkHTTPBridge(engine)
        print(f"[door-controller] HTTP bridge on {bridge.host}:{bridge.port}")
        bridge.loop_forever()
    elif args.mqtt:
        from omnilink import OmniLinkMQTTBridge
        bridge = OmniLinkMQTTBridge(engine)
        print("[door-controller] MQTT bridge started")
        bridge.loop_forever()
    else:
        run_local_demo(engine)


if __name__ == "__main__":
    main()
