"""{{ experiment_description }}

A REST API server experiment using ExperimentNode modality.

This experiment runs as a REST server, exposing `run_experiment` as an action
that can be triggered via HTTP requests or by the workcell manager.

Usage:
    Start the server:
        python {{ experiment_name }}_node.py

    Then trigger the experiment via the REST API:
        POST http://localhost:{{ server_port }}/actions/run_experiment

Generated by: madsci new experiment --modality node
Template version: {{ template_version }}
"""

from typing import Any

from madsci.common.types.experiment_types import ExperimentDesign
from madsci.experiment_application import ExperimentNode, ExperimentNodeConfig


class {{ experiment_name | pascal_case }}NodeExperiment(ExperimentNode):
    """{{ experiment_description }}

    This experiment uses the ExperimentNode modality, which runs as a REST API
    server. The experiment lifecycle is automatically managed when the
    `run_experiment` action is called via the API.

    Server mode:
        The experiment is exposed as a REST API server on port {{ server_port }}.
        The `run_experiment` method is registered as a node action and can be
        triggered via:
            POST /actions/run_experiment

    Programmatic usage:
        from {{ experiment_name }}_node import {{ experiment_name | pascal_case }}NodeExperiment
        {{ experiment_name | pascal_case }}NodeExperiment().start_server()
    """

    # Define the experiment design
    experiment_design = ExperimentDesign(
        experiment_name="{{ experiment_name | replace('_', ' ') | title }}",
        experiment_description="{{ experiment_description }}",
    )

    # Configure the experiment node server
    config = ExperimentNodeConfig(server_port={{ server_port }})

    def run_experiment(self, sample_id: str = "sample_001", **kwargs: Any) -> dict[str, Any]:
        """Execute the experiment logic.

        This method is exposed as a REST API action at POST /actions/run_experiment.
        When called via the API, the experiment lifecycle is automatically managed:
        - The experiment is started before this method runs
        - The experiment is ended after this method completes
        - Exceptions are logged and the experiment is marked as failed

        Available clients (from ExperimentBase):
        - self.workcell_client: Run workflows on the workcell
        - self.experiment_client: Manage experiment state
        - self.data_client: Store and retrieve experiment data
        - self.resource_client: Track laboratory resources
        - self.event_client / self.logger: Log events

        Args:
            sample_id: Identifier for the sample being processed.
            **kwargs: Additional keyword arguments from the API request.

        Returns:
            Dictionary containing experiment results.
        """
        # Log experiment start
        self.logger.info(
            "Starting experiment: {{ experiment_name }}",
            experiment_name="{{ experiment_name }}",
            sample_id=sample_id,
        )

        # ==========================================
        # YOUR EXPERIMENT LOGIC HERE
        # ==========================================

        # Example: Run a workflow via the workcell
        # result = self.workcell_client.run_workflow(
        #     workflow_name="my_workflow",
        #     parameters={"sample_id": sample_id},
        # )

        # Example: Store data via the data client
        # self.data_client.store_data(
        #     name="experiment_output",
        #     data={"sample_id": sample_id, "key": "value"},
        # )

        # Example: Log progress
        # self.logger.info("Processing sample...", sample_id=sample_id)

        # Placeholder result
        result = {
            "status": "completed",
            "sample_id": sample_id,
            "message": "Experiment finished successfully",
            "data": {},
        }

        # ==========================================
        # END EXPERIMENT LOGIC
        # ==========================================

        self.logger.info(
            "Experiment completed",
            result=result,
        )

        return result


def main() -> None:
    """Main entry point for the experiment node server.

    Starts the REST API server, which will listen for incoming requests
    to trigger the experiment via POST /actions/run_experiment.
    """
    {{ experiment_name | pascal_case }}NodeExperiment().start_server()


if __name__ == "__main__":
    main()
