#!/usr/bin/env python3
"""
Full RPC Server Integration Example

Demonstrates:
- RPCServer setup and protocol registration
- Command handler registration
- Authorization integration
- Message handling flow
"""

import asyncio
import logging
from pathlib import Path
from typing import Any

# For this example, we'll use mock objects since we're outside the main project
# In production, these would be imported from styrene.protocols and styrene.models


class MockRouter:
    """Mock message router for demonstration."""

    def __init__(self) -> None:
        self.sent_messages: list[tuple[str, dict[str, Any]]] = []

    async def send_message(
        self, destination: str, protocol: str, fields: dict[str, Any]
    ) -> None:
        """Mock send message."""
        self.sent_messages.append((destination, fields))
        logging.info(f"Sent to {destination[:8]}...: {fields}")


class MockIdentity:
    """Mock identity for demonstration."""

    def __init__(self, hash_str: str = "local") -> None:
        self.hash = hash_str


class MockLXMFMessage:
    """Mock LXMF message for demonstration."""

    def __init__(
        self,
        source_hash: str,
        protocol: str,
        fields: dict[str, Any],
    ) -> None:
        self.source_hash = source_hash
        self._protocol = protocol
        self.fields = fields

    def get_protocol(self) -> str:
        return self._protocol


async def main() -> None:
    """Run full server integration example."""
    logging.basicConfig(
        level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    )

    # Import components after ensuring package is installed
    try:
        from styrene_bond_rpc import RPCServer, AuthorizationService
        from styrene_bond_rpc.handlers import (
            handle_status,
            handle_exec,
            handle_reboot,
            handle_update_config,
        )
    except ImportError as e:
        print(f"Error: {e}")
        print("Install package: pip install -e packages/styrene-bond-rpc/")
        return

    # Create auth config for testing
    config_dir = Path.home() / ".config" / "styrene-bond-rpc"
    config_dir.mkdir(parents=True, exist_ok=True)
    auth_config = config_dir / "auth.yaml"

    if not auth_config.exists():
        auth_config.write_text(
            """identities:
  - hash: "admin_identity_hash_12345"
    name: "Admin User"
    permissions:
      - status
      - exec
      - reboot
      - update_config

  - hash: "monitor_identity_hash_67890"
    name: "Monitor User"
    permissions:
      - status

  - hash: "operator_identity_hash_abcde"
    name: "Operator"
    permissions:
      - status
      - exec
"""
        )
        print(f"Created auth config: {auth_config}")

    # 1. Create dependencies
    router = MockRouter()
    identity = MockIdentity()

    # 2. Initialize components
    print("\n=== Initializing Components ===")
    server = RPCServer(router, identity)
    auth_service = AuthorizationService(str(auth_config))
    print(f"✓ RPCServer initialized (protocol_id={server.protocol_id})")
    print(f"✓ AuthorizationService loaded {auth_service.get_identity_count()} identities")

    # 3. Create authorization middleware
    def create_authorized_handler(
        handler_func: Any, command_type: str
    ) -> Any:
        """Wrap handler with authorization check."""

        async def authorized_handler(message: MockLXMFMessage) -> dict[str, Any]:
            # Check authorization
            if not auth_service.is_authorized(message.source_hash, command_type):
                return {
                    "type": f"{command_type}_result",
                    "success": False,
                    "message": f"Unauthorized: {command_type} denied",
                }

            # Call original handler
            return await handler_func(message)

        return authorized_handler

    # 4. Register handlers with authorization
    print("\n=== Registering Handlers ===")
    handlers = {
        "status": handle_status,
        "exec": handle_exec,
        "reboot": handle_reboot,
        "update_config": handle_update_config,
    }

    for command_type, handler_func in handlers.items():
        authorized = create_authorized_handler(handler_func, command_type)
        server.register_handler(command_type, authorized)
        print(f"✓ Registered {command_type} (with authorization)")

    # 5. Test message handling
    print("\n=== Testing Message Handling ===")

    # Test 1: Admin can run status
    print("\n[Test 1] Admin requests status:")
    admin_msg = MockLXMFMessage(
        source_hash="admin_identity_hash_12345",
        protocol="rpc",
        fields={"type": "status", "request_id": "req-001"},
    )
    await server.handle_message(admin_msg)
    print("✓ Admin status request processed")

    # Test 2: Monitor can run status
    print("\n[Test 2] Monitor requests status:")
    monitor_msg = MockLXMFMessage(
        source_hash="monitor_identity_hash_67890",
        protocol="rpc",
        fields={"type": "status", "request_id": "req-002"},
    )
    await server.handle_message(monitor_msg)
    print("✓ Monitor status request processed")

    # Test 3: Monitor CANNOT run reboot
    print("\n[Test 3] Monitor tries reboot (should be denied):")
    monitor_reboot_msg = MockLXMFMessage(
        source_hash="monitor_identity_hash_67890",
        protocol="rpc",
        fields={"type": "reboot", "delay": 0, "request_id": "req-003"},
    )
    await server.handle_message(monitor_reboot_msg)
    print("✓ Monitor reboot request denied (as expected)")

    # Test 4: Operator can run exec
    print("\n[Test 4] Operator executes command:")
    operator_exec_msg = MockLXMFMessage(
        source_hash="operator_identity_hash_abcde",
        protocol="rpc",
        fields={
            "type": "exec",
            "command": "echo",
            "args": ["Hello", "World"],
            "request_id": "req-004",
        },
    )
    await server.handle_message(operator_exec_msg)
    print("✓ Operator exec request processed")

    # Test 5: Unknown identity denied
    print("\n[Test 5] Unknown identity tries status (should be denied):")
    unknown_msg = MockLXMFMessage(
        source_hash="unknown_identity_hash",
        protocol="rpc",
        fields={"type": "status", "request_id": "req-005"},
    )
    await server.handle_message(unknown_msg)
    print("✓ Unknown identity denied (as expected)")

    # 6. Show sent responses
    print(f"\n=== Responses Sent: {len(router.sent_messages)} ===")
    for i, (dest, fields) in enumerate(router.sent_messages, 1):
        print(f"\n[Response {i}] To: {dest[:16]}...")
        print(f"  Type: {fields.get('type')}")
        print(f"  Success: {fields.get('success', 'N/A')}")
        print(f"  Message: {fields.get('message', 'N/A')[:60]}")

    print("\n=== Integration Test Complete ===")
    print("All components working together:")
    print("  ✓ RPCServer routes messages to handlers")
    print("  ✓ Authorization middleware enforces permissions")
    print("  ✓ Command handlers execute system operations")
    print("  ✓ Responses sent back to clients")


if __name__ == "__main__":
    asyncio.run(main())
