"""
ActivityProcessor — activity monitoring state and device-level operations.

Manages the top-level activity monitoring lifecycle (start/stop flags, OS type
detection, time-range queries, tracking duration updates, and midnight rollover)
for the Workstatus desktop agent.

Thread-safety:
    ``set_force_stop()`` and ``set_status()`` are synchronous and may be called
    from any thread.  All ``async`` methods must be awaited from the async
    monitoring loop.
"""
# ws_package/managers/activity_manager.py
import datetime
import platform
import threading
from typing import List, Optional

from ws_package.entities.user_entity import UserEntity
from ws_package.entities.s3bucket_entity import S3BucketEntity
from ws_package.log.writer import LogWriter
from ws_package.exceptions.custom_exceptions import ActivityMonitoringError, ValidationError
from ws_package.utils.system import precise_sleep

logger = LogWriter.file(__name__)

class ActivityProcessor:
    """Manages activity monitoring and device operations."""
    
    def __init__(self):
        self.status = True
        self.force_stop = False
        self.tracking_scenario = None
        self.mode = None
        
        # Initialize the platform-appropriate time monitor.
        # Windows: registry-based (OptimizedWindowsTimeMonitor).
        # macOS / Linux: monotonic-drift + /etc/localtime (CrossPlatformTimeMonitor).
        if platform.system() == "Windows":
            try:
                from ws_package.monitoring.time_monitor import OptimizedWindowsTimeMonitor
                self.time_monitor = OptimizedWindowsTimeMonitor()
                logger.info("Windows time monitor initialized successfully")
            except (ImportError, RuntimeError) as e:
                logger.warning("Could not initialize Windows time monitor: %s", e)
                self.time_monitor = None
        else:
            try:
                from ws_package.monitoring.time_monitor import CrossPlatformTimeMonitor
                self.time_monitor = CrossPlatformTimeMonitor()
                logger.info("Cross-platform time monitor initialized (%s)", platform.system())
            except (ImportError, RuntimeError) as e:
                logger.warning("Could not initialize cross-platform time monitor: %s", e)
                self.time_monitor = None
    
    def get_os_type(self) -> str:
        """Return the lower-case OS name (e.g. ``'windows'``, ``'darwin'``, ``'linux'``).

        Returns:
            Lower-case string from ``platform.system()``.
        """
        return platform.system().lower()

    def is_browser(self, app_name: str) -> bool:
        """Check whether an application name belongs to a known browser.

        Args:
            app_name: Application window title or process name to test.

        Returns:
            ``True`` if the name matches a known browser substring, ``False`` otherwise.
        """
        try:
            if not app_name:
                return False
            browsers = ['chrome', 'firefox', 'safari', 'edge', 'opera', 'brave', 'vivaldi', 'brave browser', 'google chrome', 'msedge']
            app_lower = app_name.lower()
            for browser in browsers:
                if browser in app_lower:
                    return True
            return False
        except Exception as e:
            logger.error("Error checking if app is browser: %s", e, exc_info=True)
            return False
    
    async def inrange(self, start_date: datetime.datetime, end_date: datetime.datetime) -> bool:
        """Check whether the current wall-clock time falls within [start_date, end_date].

        Args:
            start_date: Inclusive range start.
            end_date: Inclusive range end.

        Returns:
            ``True`` if ``start_date <= now <= end_date``, ``False`` otherwise or on error.
        """
        try:
            current_time = datetime.datetime.now()
            return start_date <= current_time <= end_date
        except Exception as e:
            logger.error("Error checking time range: %s", e, exc_info=True)
            return False
    
    async def update_tracking_duration(self, user_entity: UserEntity):
        """Update the cumulative tracking duration record for ``user_entity``.

        Args:
            user_entity: Authenticated user whose duration should be updated.

        Raises:
            ValidationError: If ``user_entity`` is ``None``.
            ActivityMonitoringError: If the update operation fails.
        """
        try:
            if not user_entity:
                raise ValidationError("User entity is required")
            
            # Implementation for updating tracking duration
            logger.info("Updating tracking duration for user %s", user_entity.user_id)
            
        except Exception as e:
            logger.error("Error updating tracking duration: %s", e)
            raise ActivityMonitoringError(f"Failed to update tracking duration: {e}")
    
    async def midnight(self, user_entity: UserEntity, last_count: int):
        """Perform midnight rollover operations (date boundary handling).

        Args:
            user_entity: Authenticated user entity for the current session.
            last_count: The interval counter value at the time of the midnight event.

        Raises:
            ValidationError: If ``user_entity`` is ``None``.
            ActivityMonitoringError: If the midnight operation fails.
        """
        try:
            if not user_entity:
                raise ValidationError("User entity is required")
            
            logger.info("Handling midnight operations for user %s", user_entity.user_id)
            
            # Implementation for midnight operations
            await precise_sleep(1)  # Small delay to prevent rapid calls
            
        except Exception as e:
            logger.error("Error in midnight operations: %s", e)
            raise ActivityMonitoringError(f"Failed midnight operations: {e}")
    
    async def get_bucket_in_every_interval(self, user_entity: UserEntity) -> Optional[S3BucketEntity]:
        """Retrieve the S3 bucket configuration for the given user at each tracking interval.

        Args:
            user_entity: Authenticated user whose bucket configuration is needed.

        Returns:
            An :class:`~ws_package.entities.s3bucket_entity.S3BucketEntity` if found,
            or ``None`` if not configured.

        Raises:
            ValidationError: If ``user_entity`` is ``None``.
            ActivityMonitoringError: If the retrieval fails.
        """
        try:
            if not user_entity:
                raise ValidationError("User entity is required")
            
            # Implementation for getting bucket configuration
            logger.info("Getting bucket configuration for user %s", user_entity.user_id)
            
            return None  # Placeholder - implement actual bucket retrieval
            
        except Exception as e:
            logger.error("Error getting bucket configuration: %s", e)
            raise ActivityMonitoringError(f"Failed to get bucket configuration: {e}")
    
    async def update_interval(self, user_entity: UserEntity):
        """Refresh the organisation's configured tracking interval from the API.

        Args:
            user_entity: Authenticated user entity supplying auth credentials.

        Raises:
            ValidationError: If ``user_entity`` is ``None``.
            ActivityMonitoringError: If the update fails.
        """
        try:
            if not user_entity:
                raise ValidationError("User entity is required")
            
            logger.info("Updating interval for user %s", user_entity.user_id)
            
            # Implementation for updating interval
            
        except Exception as e:
            logger.error("Error updating interval: %s", e)
            raise ActivityMonitoringError(f"Failed to update interval: {e}")
    
    async def getStartingSlot(self):
        """Return the start of the first tracking time slot.

        Returns:
            A ``datetime.datetime`` aligned to the first interval boundary.

        Raises:
            ActivityMonitoringError: If the slot cannot be determined.
        """
        try:
            # Implementation for getting starting slot
            return datetime.datetime.now()
        except Exception as e:
            logger.error("Error getting starting slot: %s", e)
            raise ActivityMonitoringError(f"Failed to get starting slot: {e}")
    
    async def getCurrentSlot(self):
        """Return the start of the current tracking time slot.

        Returns:
            A ``datetime.datetime`` aligned to the current interval boundary.

        Raises:
            ActivityMonitoringError: If the slot cannot be determined.
        """
        try:
            # Implementation for getting current slot
            return datetime.datetime.now()
        except Exception as e:
            logger.error("Error getting current slot: %s", e)
            raise ActivityMonitoringError(f"Failed to get current slot: {e}")
    
    def set_force_stop(self, value: bool) -> None:
        """Set the force-stop flag to immediately halt monitoring.

        Args:
            value: ``True`` to request a forced stop; ``False`` to clear it.
        """
        self.force_stop = value
        logger.info("Force stop set to: %s", value)

    def get_status(self) -> bool:
        """Return the current monitoring status flag.

        Returns:
            ``True`` when monitoring is active, ``False`` when stopped.
        """
        return self.status

    def set_status(self, value: bool) -> None:
        """Set the monitoring status flag.

        Args:
            value: ``True`` to mark monitoring as active, ``False`` to stop.
        """
        self.status = value
        logger.info("Status set to: %s", value)
