"""{{ module_description }}

This module implements a MADSci REST node for the {{ module_name }} instrument
with measurement, calibration, and data acquisition capabilities.

Generated by: madsci new module --template module/instrument
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 }} instrument
    with measurement and calibration capabilities.

    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
    """

    # 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 instrument node and create resource templates."""
        # 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 instrument and initialize it
        self._interface.connect()
        self._interface.initialize()

        # Create instrument slot template
        instrument_slot = Slot(
            resource_name="{{ module_name }}_slot",
            resource_class="{{ module_name | pascal_case }}Slot",
            capacity=1,
            attributes={
                "slot_type": "instrument_slot",
                "accessible": True,
                "description": "{{ module_name | pascal_case }} instrument sample slot",
            },
        )

        self.resource_client.init_template(
            resource=instrument_slot,
            template_name="{{ module_name }}_slot",
            description=(
                "Template for {{ module_name }} instrument slot. "
                "Represents positions where samples can be placed for measurement."
            ),
            required_overrides=["resource_name"],
            tags=["{{ module_name }}", "slot", "instrument"],
            created_by=self.node_definition.node_id,
            version="1.0.0",
        )

        # Initialize instrument slot resource instance
        slot_resource_name = f"{{ module_name }}_slot_{self.node_definition.node_name}"
        self.instrument_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 instrument slot resource from template: {self.instrument_slot.resource_id}"
        )

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

    def shutdown_handler(self) -> None:
        """Clean shutdown of the instrument node."""
        self.logger.log("Shutting down {{ module_name }} instrument 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.

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

    @action
    def measure(self, channel: str = "") -> dict:
        """Take a measurement reading from the instrument.

        Args:
            channel: Optional channel or sensor to read from.

        Returns:
            dict: Measurement reading data.
        """
        reading = self._interface.measure(channel=channel or None)
        time.sleep(self.config.wait_time)
        return reading.model_dump()

    @action
    def calibrate(self) -> dict:
        """Calibrate the instrument.

        Returns:
            dict: Calibration result data.
        """
        result = self._interface.calibrate()
        time.sleep(self.config.wait_time)
        return result.model_dump()

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

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

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

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


def main() -> None:
    """Entry point for the {{ module_name }} instrument 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()
