#!/usr/bin/env python3
"""
MyCalculation - Default calculation implementation for BlackAnt SDK.

This class provides a production-ready wrapper around the simple_calc module,
implementing the CalculationBase interface required by the BlackAnt task system.
"""

from typing import Dict, Any, Optional
import logging

from calculation.base import CalculationBase
from calculation.impl.simple_calc import calculate


class MyCalculation(CalculationBase):
    """
    Default calculation implementation using simple_calc logic.

    This class implements the CalculationBase interface and provides
    state machine compatibility (set_up → run → tear_down).

    Attributes:
        _logger: Logger instance for calculation events
        _kwargs: Keyword arguments passed to calculation
        _result: Calculation result (None until run() completes)
        _is_running: Flag indicating calculation is in progress
    """

    def __init__(self, logger: logging.Logger, **kwargs: Any) -> None:
        """
        Initialize MyCalculation with logger and configuration.

        Args:
            logger: Logger instance for calculation events
            **kwargs: Additional keyword arguments for calculation configuration
                     Expected keys:
                     - data: Dict with calculation input (default: kwargs itself)
                     - numbers: List of numbers to calculate (fallback)
        """
        super().__init__(logger)
        self._kwargs = kwargs
        self._result: Optional[Dict[str, Any]] = None
        self._is_running = False

        self._logger.info("MyCalculation instance created")
        self._logger.debug(f"Configuration: {kwargs}")

    def set_up(self) -> None:
        """
        Prepare calculation resources (state machine: idle → set_up).

        This method is called by the task system before run().
        Performs validation and resource initialization.
        """
        self._logger.info("MyCalculation setup started")

        # Validate input data structure
        data = self._kwargs.get('data', self._kwargs)
        if not isinstance(data, dict):
            self._logger.warning(f"Expected dict data, got {type(data).__name__}")

        self._logger.info("MyCalculation setup completed successfully")

    def run(self) -> None:
        """
        Execute the calculation (state machine: set_up → running).

        This method performs the actual calculation using simple_calc.calculate().
        Results are stored in self._result and accessible via the result property.
        """
        self._logger.info("MyCalculation execution started")
        self._is_running = True

        try:
            # Extract data from kwargs (task sends data in 'data' key or root level)
            data = self._kwargs.get('data', self._kwargs)

            # Execute calculation using simple_calc function
            self._logger.debug(f"Calling calculate() with data: {data}")
            self._result = calculate(data)

            self._logger.info(f"Calculation completed successfully: {self._result}")

        except Exception as exc:
            self._logger.error(f"Calculation failed: {exc}", exc_info=True)
            self._result = {
                'error': str(exc),
                'status': 'failed'
            }
            raise

        finally:
            self._is_running = False

    def tear_down(self) -> None:
        """
        Clean up calculation resources (state machine: running → tear_down).

        This method is called by the task system after run() completes.
        Performs cleanup and resource release.
        """
        self._logger.info("MyCalculation teardown started")

        # Release resources (if any)
        self._is_running = False

        self._logger.info("MyCalculation teardown completed")

    def stop(self) -> None:
        """
        Stop calculation execution (manual interrupt).

        This method is called when the task is manually stopped.
        Sets the running flag to False to signal interruption.
        """
        self._logger.warning("MyCalculation stop requested")
        self._is_running = False

        if self._result is None:
            self._result = {
                'status': 'stopped',
                'message': 'Calculation was stopped before completion'
            }

        self._logger.info("MyCalculation stopped")

    @property
    def result(self) -> Optional[Dict[str, Any]]:
        """
        Get calculation result.

        Returns:
            Optional[Dict[str, Any]]: Calculation result or None if not yet executed
                Expected structure:
                {
                    'result': int/float,      # Sum of numbers
                    'count': int,             # Number count
                    'average': float,         # Average value
                    'timestamp': str,         # ISO format timestamp
                    'service_name': str       # Service identifier
                }
        """
        return self._result
