"""
알림 관리자

Windows 토스트 알림 및 팝업 다이얼로그를 관리하는 모듈입니다.
winotify를 사용한 시스템 알림과 CustomTkinter 기반 팝업을 제공합니다.

주요 기능:
    - Windows 토스트 알림
    - 팝업 다이얼로그 (단건/다건)
    - 시작 알림
    - 알림 설정 관리

의존성:
    - winotify: Windows 토스트 알림
    - view.dialogs.notification_dialog: 팝업 다이얼로그

작성자: KH.Choi
최종 수정: 2026-02-17
버전: 1.0 (Controller에서 분리)
"""
from pathlib import Path
from typing import Optional, Callable

try:
    from winotify import Notification, audio
    HAS_WINOTIFY = True
except ImportError:
    HAS_WINOTIFY = False

from utils.path_utils import get_base_dir
from utils.logger import get_logger


class NotificationManager:
    """
    알림 관리자
    
    Windows 토스트 알림 및 팝업 다이얼로그를 관리합니다.
    알림 설정에 따라 소리 재생 여부를 제어합니다.
    
    Attributes:
        logger: 로거 인스턴스
        root: Tkinter 루트 윈도우 (팝업용)
        icon_path (Path): 알림 아이콘 경로
        popup_callback (Callable): 팝업 다이얼로그 콜백
    
    주요 메서드:
        show_startup_notification: 시작 알림 표시
        show_toast: Windows 토스트 알림 표시
        show_popup: 팝업 다이얼로그 표시
    
    사용 예시:
        >>> notifier = NotificationManager(root, logger)
        >>> notifier.show_startup_notification()
        >>> notifier.show_toast("신규 VOC", "1호선 서면역 소음 발생")
    """
    
    def __init__(self, root, logger=None):
        """
        알림 관리자 초기화
        
        Args:
            root: Tkinter 루트 윈도우
            logger: 로거 인스턴스 (선택)
        """
        self.logger = logger or get_logger("NotificationManager")
        self.root = root
        self.icon_path = get_base_dir() / "assets" / "app_icon.png"
        
        # 팝업 다이얼로그 콜백 (Controller에서 주입)
        self.popup_callback: Optional[Callable] = None
        
        # winotify 사용 가능 여부 확인
        if not HAS_WINOTIFY:
            self.logger.warning("winotify 모듈이 설치되지 않았습니다. 토스트 알림이 비활성화됩니다.")
    
    def set_popup_callback(self, callback: Callable):
        """
        팝업 다이얼로그 콜백 설정 (의존성 주입)
        
        Args:
            callback: 팝업 생성 함수 (title, msg, voc_id) -> None
        """
        self.popup_callback = callback
    
    def show_startup_notification(self):
        """
        프로그램 시작 알림 표시
        
        트레이 아이콘이 활성화되었음을 사용자에게 알립니다.
        """
        if not HAS_WINOTIFY:
            self.logger.info("시작 알림 생략 (winotify 미설치)")
            return
        
        try:
            toast = Notification(
                app_id="VOC Monitor",
                title="VOC 모니터링 시작",
                msg="프로그램이 백그라운드에서 실행 중입니다.\n트레이 아이콘을 확인해주세요.",
                icon=str(self.icon_path),
                duration="short"
            )
            toast.set_audio(audio.Default, loop=False)
            toast.show()
            self.logger.info("시작 알림 표시됨")
        except Exception as e:
            self.logger.error(f"시작 알림 표시 실패: {e}")
    
    def show_toast(
        self, 
        title: str, 
        message: str, 
        duration: str = "short",
        with_sound: bool = True
    ):
        """
        Windows 토스트 알림 표시
        
        Args:
            title: 알림 제목
            message: 알림 내용
            duration: 표시 시간 ("short" 또는 "long")
            with_sound: 소리 재생 여부
        """
        if not HAS_WINOTIFY:
            self.logger.debug(f"토스트 알림 생략: {title}")
            return
        
        try:
            toast = Notification(
                app_id="VOC Monitor",
                title=title,
                msg=message,
                icon=str(self.icon_path),
                duration=duration
            )
            
            if with_sound:
                toast.set_audio(audio.Default, loop=False)
            
            toast.show()
            self.logger.debug(f"토스트 알림 표시: {title}")
        except Exception as e:
            self.logger.error(f"토스트 알림 표시 실패: {e}")
    
    def show_popup(self, title: str, message: str, voc_id: Optional[str] = None):
        """
        팝업 다이얼로그 표시
        
        메인 스레드에서 실행되도록 after()를 사용합니다.
        
        Args:
            title: 팝업 제목
            message: 팝업 내용
            voc_id: VOC ID (클릭 시 상세 조회용, 선택)
        """
        if not self.popup_callback:
            self.logger.warning("팝업 콜백이 설정되지 않았습니다.")
            return
        
        # 메인 스레드에서 실행 (스레드 안전)
        self.root.after(0, lambda: self.popup_callback(title, message, voc_id))
        self.logger.debug(f"팝업 다이얼로그 표시: {title}")
    
    def show_notification(
        self, 
        title: str, 
        message: str, 
        voc_id: Optional[str] = None,
        use_toast: bool = True,
        use_popup: bool = True,
        with_sound: bool = True
    ):
        """
        통합 알림 표시
        
        토스트 알림과 팝업 다이얼로그를 동시에 표시합니다.
        
        Args:
            title: 알림 제목
            message: 알림 내용
            voc_id: VOC ID (선택)
            use_toast: 토스트 알림 사용 여부
            use_popup: 팝업 다이얼로그 사용 여부
            with_sound: 소리 재생 여부
        """
        if use_toast:
            self.show_toast(title, message, with_sound=with_sound)
        
        if use_popup:
            self.show_popup(title, message, voc_id)
