import psutil
from datetime import datetime

from modules.config import Config


class SystemMonitor:
    def __init__(self, messenger, ollama_manager):
        self.messenger = messenger
        self.ollama_monitor = ollama_manager
        self.last_health_check = datetime.now()

        # CPU 서킷 브레이커 상태
        self._cpu_overload_count = 0       # 연속 과부하 횟수
        self._circuit_open = False         # 서킷 브레이커 발동 여부
        self._circuit_open_since = None

    def is_cpu_critical(self):
        """서킷 브레이커가 발동 상태인지 반환 (True이면 분석 사이클 스킵)"""
        return self._circuit_open

    def reset_circuit(self):
        """서킷 브레이커 수동 리셋"""
        if self._circuit_open:
            print("[Monitor] CPU Circuit Breaker RESET")
        self._circuit_open = False
        self._cpu_overload_count = 0
        self._circuit_open_since = None

    def check_health(self):
        """시스템 상태 점검 및 알림 (CPU, RAM, GPU) - 3분마다 실행"""
        now = datetime.now()
        if (now - self.last_health_check).total_seconds() < 180:
            return

        self.last_health_check = now
        alerts = []

        # 1. CPU Check
        cpu_usage = psutil.cpu_percent(interval=1)  # 1초 측정 (더 정확)

        if cpu_usage > Config.CPU_CIRCUIT_BREAKER_THRESHOLD:
            self._cpu_overload_count += 1

            # 상위 프로세스 조회
            top_processes = []
            for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
                try:
                    if proc.info['name'] in ('System Idle Process', 'Idle'):
                        continue
                    top_processes.append(proc.info)
                except (psutil.NoSuchProcess, psutil.AccessDenied):
                    pass

            top_processes.sort(key=lambda x: x['cpu_percent'], reverse=True)
            top_3_str = ""
            for p in top_processes[:3]:
                top_3_str += f"\n- {p['name']} ({p['cpu_percent']}%)"

            # 서킷 브레이커 발동 조건
            if self._cpu_overload_count >= Config.CPU_CIRCUIT_BREAKER_CONSECUTIVE:
                if not self._circuit_open:
                    self._circuit_open = True
                    self._circuit_open_since = now
                    alerts.append(
                        f"🔴 [CPU Circuit Breaker OPEN] {cpu_usage}% × {self._cpu_overload_count}회 연속\n"
                        f"⛔ 분석 사이클 일시 중단 (5분 후 자동 복구)\nTop Processes:{top_3_str}"
                    )
                    print(f"[Monitor] CPU Circuit Breaker OPEN! CPU={cpu_usage}%")
            else:
                alerts.append(
                    f"⚠️ [CPU Overload] Usage: {cpu_usage}% ({self._cpu_overload_count}회)\nTop Processes:{top_3_str}"
                )
        else:
            # CPU 정상 → 카운터 리셋
            if self._cpu_overload_count > 0:
                print(f"[Monitor] CPU 정상화 ({cpu_usage}%). 카운터 리셋.")
            self._cpu_overload_count = 0

            # 서킷 브레이커가 열린 후 5분 경과 시 자동 복구
            if self._circuit_open and self._circuit_open_since:
                elapsed = (now - self._circuit_open_since).total_seconds()
                if elapsed >= 300:  # 5분
                    self._circuit_open = False
                    self._circuit_open_since = None
                    alerts.append("✅ [CPU Circuit Breaker CLOSED] 시스템 안정화. 분석 재개.")
                    print("[Monitor] CPU Circuit Breaker CLOSED. 분석 재개.")

        # 2. RAM Check
        ram = psutil.virtual_memory()
        if ram.percent > 90:
            alerts.append(f"⚠️ [RAM High] Usage: {ram.percent}% (Free: {ram.available / 1024**3:.1f}GB)")

        # 3. GPU Check
        if self.ollama_monitor:
            gpu_status = self.ollama_monitor.get_gpu_status()
            temp = gpu_status.get('temp', 0)
            if temp > 80:
                alerts.append(f"🔥 [GPU Overheat] Temp: {temp}°C")

        # 알림 전송 (텔레그램 비활성화 - 콘솔 로그만 사용)
        if alerts:
            # 콘솔에만 출력
            for alert in alerts:
                print(f"[Monitor] {alert}")

            # [비활성화] 텔레그램 알림 - 필요시 재활성화
            # msg = "🔔 <b>[System Health Alert]</b>\n" + "\n".join(alerts)
            # if self.messenger:
            #     self.messenger.send_message(msg)
