"""
Performance monitoring during data operations.

Tracks memory usage, processing time, and provides warnings for resource constraints.
"""

import time
import psutil
import threading
from typing import Optional


class PerformanceMonitor:
    """Monitor performance during data operations"""

    def __init__(self, memory_limit_gb: float):
        self.memory_limit_gb = memory_limit_gb
        self.start_time: Optional[float] = None
        self.peak_memory_gb: float = 0.0
        self.current_operation: Optional[str] = None
        self.monitoring = False
        self.monitor_thread: Optional[threading.Thread] = None

    def start_monitoring(self, operation_name: str):
        """Start monitoring for an operation"""
        self.start_time = time.time()
        self.current_operation = operation_name
        self.peak_memory_gb = 0.0
        self.monitoring = True

        # Start background monitoring thread
        self.monitor_thread = threading.Thread(target=self._monitor_loop, daemon=True)
        self.monitor_thread.start()

    def stop_monitoring(self):
        """Stop monitoring"""
        self.monitoring = False
        if self.monitor_thread:
            self.monitor_thread.join(timeout=1.0)

    def get_elapsed_time(self) -> float:
        """Get elapsed time since monitoring started"""
        if self.start_time is None:
            return 0.0
        return time.time() - self.start_time

    def get_peak_memory(self) -> float:
        """Get peak memory usage in GB"""
        return self.peak_memory_gb

    def _monitor_loop(self):
        """Background monitoring loop"""
        while self.monitoring:
            try:
                # Track memory usage
                memory_info = psutil.virtual_memory()
                current_memory_gb = memory_info.used / (1024**3)
                self.peak_memory_gb = max(self.peak_memory_gb, current_memory_gb)

                # Check for memory pressure
                if current_memory_gb > self.memory_limit_gb * 0.9:
                    print(
                        f"⚠️  High memory usage: {current_memory_gb:.1f}GB "
                        f"(limit: {self.memory_limit_gb:.1f}GB)"
                    )

                time.sleep(1.0)  # Check every second

            except Exception as e:
                print(f"Monitoring error: {e}")
                break
