"""Fake interface for {{ module_name }} camera.

This module provides a simulated interface for testing without hardware.
It implements the same methods as the real interface but operates entirely
in memory, with configurable latency and full state tracking for testing.

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

import logging
import time
from typing import Any, Optional

from {{ module_name }}_types import (
    {{ module_name | pascal_case }}CaptureResult,
    {{ module_name | pascal_case }}InterfaceConfig,
)

logger = logging.getLogger(__name__)


class {{ module_name | pascal_case }}FakeInterface:
    """Fake interface for testing {{ module_name }} without hardware.

    This class simulates camera behavior including full lifecycle management
    (connect, initialize, shutdown, disconnect), image capture, and
    configuration. It is designed for:
    - Development without physical hardware
    - Automated testing in CI/CD
    - Demo and training purposes
    - Debugging workflow logic

    Example:
        >>> interface = {{ module_name | pascal_case }}FakeInterface(simulated_latency=0.01)
        >>> interface.connect()
        >>> interface.initialize()
        >>> result = interface.capture(exposure_ms=50.0)
        >>> status = interface.get_status()
        >>> interface.shutdown()
        >>> interface.disconnect()
    """

    def __init__(
        self,
        config: Optional[{{ module_name | pascal_case }}InterfaceConfig] = None,
        simulated_latency: float = 0.1,
        **kwargs: Any,
    ) -> None:
        """Initialize the fake interface.

        Args:
            config: Interface configuration. Uses defaults if None.
            simulated_latency: Simulated operation time in seconds.
            **kwargs: Additional configuration (ignored in fake mode).
        """
        self._config = config or {{ module_name | pascal_case }}InterfaceConfig(**kwargs)
        self._simulated_latency = simulated_latency
        self._connected = False
        self._initialized = False
        self._operation_count = 0
        self._capture_count = 0
        self._last_capture: Optional[{{ module_name | pascal_case }}CaptureResult] = None
        self._state: dict[str, Any] = {}
        self._capture_history: list[dict[str, Any]] = []

    @property
    def is_connected(self) -> bool:
        """Check if the interface is connected."""
        return self._connected

    @property
    def is_initialized(self) -> bool:
        """Check if the camera has been initialized."""
        return self._initialized

    @property
    def operation_count(self) -> int:
        """Get the number of operations performed."""
        return self._operation_count

    @property
    def capture_history(self) -> list[dict[str, Any]]:
        """Get the history of image captures."""
        return list(self._capture_history)

    def connect(self) -> None:
        """Simulate establishing connection to the camera."""
        logger.info("[FAKE] Connecting to simulated {{ module_name }} camera...")
        time.sleep(self._simulated_latency)
        self._connected = True
        self._state["connected_at"] = time.time()
        logger.info("[FAKE] Connected to simulated {{ module_name }} camera")

    def disconnect(self) -> None:
        """Simulate closing connection to the camera."""
        if self._connected:
            logger.info("[FAKE] Disconnecting from simulated {{ module_name }} camera...")
            self._connected = False
            self._initialized = False
            self._state["disconnected_at"] = time.time()
            logger.info("[FAKE] Disconnected from simulated {{ module_name }} camera")

    def initialize(self) -> None:
        """Simulate camera initialization.

        Raises:
            RuntimeError: If not connected.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")

        logger.info("[FAKE] Initializing simulated {{ module_name }} camera...")
        time.sleep(self._simulated_latency)
        self._initialized = True
        self._state["initialized_at"] = time.time()
        logger.info("[FAKE] Simulated {{ module_name }} camera initialized")

    def shutdown(self) -> None:
        """Simulate camera shutdown.

        Raises:
            RuntimeError: If not connected.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")

        logger.info("[FAKE] Shutting down simulated {{ module_name }} camera...")
        time.sleep(self._simulated_latency)
        self._initialized = False
        self._state["shutdown_at"] = time.time()
        logger.info("[FAKE] Simulated {{ module_name }} camera shut down")

    def capture(
        self,
        exposure_ms: Optional[float] = None,
        save_path: Optional[str] = None,
    ) -> {{ module_name | pascal_case }}CaptureResult:
        """Simulate capturing an image from the camera.

        Args:
            exposure_ms: Exposure time in milliseconds. Uses default if None.
            save_path: Path to save the captured image (simulated, no file written).

        Returns:
            {{ module_name | pascal_case }}CaptureResult: Simulated capture result.

        Raises:
            RuntimeError: If not connected or not initialized.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")
        if not self._initialized:
            raise RuntimeError("Camera not initialized. Call initialize() first.")

        time.sleep(self._simulated_latency)

        effective_exposure = exposure_ms if exposure_ms is not None else self._config.exposure_ms

        # Parse resolution
        width, height = (int(x) for x in self._config.resolution.split("x"))

        self._operation_count += 1
        self._capture_count += 1

        result = {{ module_name | pascal_case }}CaptureResult(
            image_path=save_path,
            width=width,
            height=height,
            timestamp=time.time(),
            metadata={
                "exposure_ms": effective_exposure,
                "gain": self._config.gain,
                "resolution": self._config.resolution,
                "capture_number": self._capture_count,
                "simulated": True,
            },
        )
        self._last_capture = result

        capture_record = {
            "exposure_ms": effective_exposure,
            "save_path": save_path,
            "width": width,
            "height": height,
            "operation_number": self._operation_count,
            "capture_number": self._capture_count,
            "timestamp": time.time(),
        }
        self._capture_history.append(capture_record)
        self._state["last_capture_time"] = time.time()

        logger.info(
            f"[FAKE] Simulated image capture: {width}x{height}, exposure={effective_exposure}ms"
        )
        return result

    def configure(
        self,
        exposure_ms: Optional[float] = None,
        gain: Optional[float] = None,
        resolution: Optional[str] = None,
    ) -> dict:
        """Simulate updating camera settings.

        Args:
            exposure_ms: New exposure time in milliseconds.
            gain: New gain multiplier.
            resolution: New resolution string (WIDTHxHEIGHT).

        Returns:
            dict: The updated camera settings.

        Raises:
            RuntimeError: If not connected.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")

        if exposure_ms is not None:
            self._config.exposure_ms = exposure_ms
        if gain is not None:
            self._config.gain = gain
        if resolution is not None:
            self._config.resolution = resolution

        self._operation_count += 1

        logger.info("[FAKE] Updated simulated {{ module_name }} camera configuration")
        return {
            "exposure_ms": self._config.exposure_ms,
            "gain": self._config.gain,
            "resolution": self._config.resolution,
        }

    def get_image_info(self) -> dict:
        """Get information about the last simulated capture.

        Returns:
            dict: Information about the last capture, or empty dict if
                no images have been captured yet.

        Raises:
            RuntimeError: If not connected.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")

        if self._last_capture is None:
            return {}

        return self._last_capture.model_dump()

    def get_status(self) -> dict:
        """Get the simulated camera status.

        Returns:
            dict: Simulated camera status information.

        Raises:
            RuntimeError: If not connected.
        """
        if not self._connected:
            raise RuntimeError("Not connected. Call connect() first.")

        return {
            "connected": self._connected,
            "initialized": self._initialized,
            "resolution": self._config.resolution,
            "exposure_ms": self._config.exposure_ms,
            "capture_count": self._capture_count,
            "operation_count": self._operation_count,
            "last_capture_time": self._state.get("last_capture_time"),
        }

    def get_state(self) -> dict[str, Any]:
        """Get the current internal state (useful for testing).

        Returns:
            Dictionary of internal state including connection status,
            initialization status, operation count, and capture history.
        """
        return {
            "connected": self._connected,
            "initialized": self._initialized,
            "operation_count": self._operation_count,
            "capture_count": self._capture_count,
            "capture_history_length": len(self._capture_history),
            **self._state,
        }

    def reset_state(self) -> None:
        """Reset internal state (useful for testing).

        Clears operation count, capture history, and internal state
        while preserving connection and initialization status.
        """
        self._operation_count = 0
        self._capture_count = 0
        self._last_capture = None
        self._capture_history = []
        self._state = {}
