"""{{ module_description }}

This module implements a MADSci REST node for the {{ module_name }} device
with full lifecycle management (initialize, shutdown, status) and
resource management using templates and slots.

Generated by: madsci new module --template module/device
Template version: {{ template_version }}
"""

import argparse
import time
from typing import Any

from madsci.common.types.resource_types import Slot
from madsci.node_module.helpers import action
from madsci.node_module.rest_node_module import RestNode

from {{ module_name }}_interface import {{ module_name | pascal_case }}Interface
from {{ module_name }}_fake_interface import {{ module_name | pascal_case }}FakeInterface
from {{ module_name }}_types import {{ module_name | pascal_case }}NodeConfig


class {{ module_name | pascal_case }}Node(RestNode):
    """{{ module_description }}

    This node provides a REST API for controlling the {{ module_name }} device
    with full lifecycle management and resource tracking.

    Node Architecture:
    - Inherits from RestNode for HTTP API exposure
    - Uses @action decorator to expose callable methods
    - Manages resources through ResourceClient integration
    - Logs all operations through EventClient

    Resource Management:
    - Creates and manages device slot templates (Slot resources)
    - Initializes device slot resource instances
    - Tracks resource state changes
    """

    # Hardware interface instance (initialized in startup_handler)
    _interface: Any = None

    # Configuration instance with node-specific settings
    config: {{ module_name | pascal_case }}NodeConfig = {{ module_name | pascal_case }}NodeConfig()

    # Pydantic model class for configuration validation
    config_model = {{ module_name | pascal_case }}NodeConfig

    def startup_handler(self) -> None:
        """Initialize the device node and create resource templates.

        This method is called when the node starts up or restarts. It performs:
        1. Hardware interface initialization (real or fake based on config)
        2. Device connection and initialization
        3. Resource template creation for device slots
        4. Instantiation of specific resources
        5. Registration of resources with the resource manager
        """
        # Create the appropriate interface based on configuration
        if self.config.interface_type == "fake":
            self._interface = {{ module_name | pascal_case }}FakeInterface()
        else:
            self._interface = {{ module_name | pascal_case }}Interface()

        # Connect to the device and initialize it
        self._interface.connect()
        self._interface.initialize()

        # Create device slot template - represents positions where items can be placed
        device_slot = Slot(
            resource_name="{{ module_name }}_slot",
            resource_class="{{ module_name | pascal_case }}Slot",
            capacity=1,
            attributes={
                "slot_type": "device_slot",
                "accessible": True,
                "description": "{{ module_name | pascal_case }} device slot for placing items",
            },
        )

        self.resource_client.init_template(
            resource=device_slot,
            template_name="{{ module_name }}_slot",
            description=(
                "Template for {{ module_name }} device slot. "
                "Represents positions where items can be placed on the device."
            ),
            required_overrides=["resource_name"],
            tags=["{{ module_name }}", "slot", "device"],
            created_by=self.node_definition.node_id,
            version="1.0.0",
        )

        # Initialize device slot resource instance
        slot_resource_name = f"{{ module_name }}_slot_{self.node_definition.node_name}"
        self.device_slot = self.resource_client.create_resource_from_template(
            template_name="{{ module_name }}_slot",
            resource_name=slot_resource_name,
            add_to_database=True,
        )
        self.logger.log(
            f"Initialized device slot resource from template: {self.device_slot.resource_id}"
        )

        self.logger.log("{{ module_name | pascal_case }} device node initialized!")

    def shutdown_handler(self) -> None:
        """Clean shutdown of the device node.

        This method is called when the node is being shut down or restarted.
        It safely shuts down the device and closes connections.
        """
        self.logger.log("Shutting down {{ module_name }} device node")
        if self._interface:
            self._interface.shutdown()
            self._interface.disconnect()

    def state_handler(self) -> dict[str, Any]:
        """Report current node state for monitoring and debugging.

        This method is called periodically by the MADSci framework to collect
        node status information for dashboard displays, health monitoring,
        and scheduling decisions.

        Returns:
            dict: Current node state including device status information.
        """
        if self._interface and self._interface.is_connected:
            self.node_state = self._interface.get_status()

    @action
    def execute_command(self, command: str) -> str:
        """Execute a command on the device.

        This action sends a command string to the device hardware and
        returns the command that was executed.

        Args:
            command: Device-specific command string to execute.

        Returns:
            str: Echo of the executed command for confirmation.
        """
        self._interface.execute_command(command)
        time.sleep(self.config.wait_time)
        return command

    @action
    def get_device_status(self) -> dict:
        """Get the current status of the device.

        This action queries the device for its current status information,
        including connection state, initialization state, and any
        device-specific status data.

        Returns:
            dict: Device status information.
        """
        return self._interface.get_status()

    @action
    def reset_device(self) -> str:
        """Reset the device to its initial state.

        This action performs a device reset by shutting down and
        re-initializing the device. Useful for recovering from
        error states or preparing for a new experiment.

        Returns:
            str: Confirmation message.
        """
        self.logger.log("Resetting {{ module_name }} device...")
        self._interface.shutdown()
        self._interface.initialize()
        self.logger.log("{{ module_name | pascal_case }} device reset complete")
        return "Device reset successfully"


def main() -> None:
    """Entry point for the {{ module_name }} device node."""
    parser = argparse.ArgumentParser(description="{{ module_description }}")
    parser.add_argument(
        "--fake",
        action="store_true",
        help="Use fake interface for testing without hardware",
    )
    parser.add_argument(
        "--port",
        type=int,
        default={{ port }},
        help="Port to run the node on (default: {{ port }})",
    )
    args = parser.parse_args()

    node = {{ module_name | pascal_case }}Node()
    if args.fake:
        node.config.interface_type = "fake"
    node.config.node_url = f"http://localhost:{args.port}/"
    node.start_node()


if __name__ == "__main__":
    main()
