"""
UI 관리자 (UI Manager)

AppController의 UI 창 열기 로직을 전담합니다.
다이얼로그 생성 및 포커스 관리를 담당합니다.

주요 기능:
    - 히스토리 다이얼로그 열기
    - 설정 다이얼로그 열기
    - 통계 다이얼로그 열기
    - 상세 조회 다이얼로그 열기

작성자: KH.Choi
최종 수정: 2026-02-17
버전: 1.0 (Controller에서 분리)
"""
from tkinter import messagebox

from core.exceptions import DatabaseError


class UIManager:
    """
    UI 다이얼로그 관리자
    
    각종 다이얼로그 창의 생성 및 포커스 관리를 담당합니다.
    이미 열려있는 창은 재사용하고 포커스만 이동시킵니다.
    
    Attributes:
        controller: AppController 인스턴스
        db: VOCDatabase 인스턴스
        logger: 로거 인스턴스
        root: Tkinter 루트 윈도우
        list_window: HistoryDialog 인스턴스 (캐시)
        settings_window: SettingsDialog 인스턴스 (캐시)
    
    주요 메서드:
        open_list_view: 히스토리 창 열기
        open_settings: 설정 창 열기
        open_statistics: 통계 창 열기
        request_detail_popup: 상세 조회 팝업
    
    사용 예시:
        >>> ui_mgr = UIManager(controller)
        >>> ui_mgr.open_list_view(focus_id="12345")
    """
    
    def __init__(self, controller):
        """
        UIManager 초기화
        
        Args:
            controller (AppController): 메인 컨트롤러 인스턴스
        """
        self.controller = controller
        self.db = controller.db
        self.logger = controller.logger
        self.root = controller.root
        
        # 창 인스턴스 캐시
        self.list_window = None
        self.settings_window = None
    
    # ========================================================================
    # 히스토리 창 (History Dialog)
    # ========================================================================
    
    def open_list_view(self, focus_id=None):
        """
        수집 목록 창을 엽니다.
        
        이미 열려 있다면 포커스를 맞추고 데이터를 갱신합니다.
        메인 스레드에서 실행을 보장합니다.
        
        Args:
            focus_id (str, optional): 창을 연 후 상세 팝업을 띄울 VOC ID
        """
        # 메인 스레드에서 실행 보장
        self.root.after(0, lambda: self._actual_open_list(focus_id))
    
    def _actual_open_list(self, focus_id):
        """
        실제 목록 창 생성 로직 (내부 메서드, 메인 스레드 실행 필수)
        
        Args:
            focus_id (str, optional): VOC ID
        """
        try:
            if self.list_window is None or not self.list_window.winfo_exists():
                # 새 창 생성
                rows = self.db.get_all_posts()
                formatted = self.controller._format_rows(rows)
                
                from view.dialogs.history_dialog import HistoryDialog
                self.list_window = HistoryDialog(self.controller, formatted)
            else:
                # 기존 창 재사용
                self.list_window.refresh_data_only()
                self.list_window.deiconify()
                self.list_window.focus_force()
            
            # 특정 게시글 바로 조회
            if focus_id and isinstance(focus_id, str):
                self.request_detail_popup(focus_id)
        
        except DatabaseError as e:
            self.logger.error(f"목록 조회 실패: {e.message}")
            messagebox.showerror("오류", f"목록을 불러올 수 없습니다.\n{e.message}")
        except Exception as e:
            self.logger.error(f"목록 창 열기 실패: {e}", exc_info=True)
            messagebox.showerror("오류", f"목록 창을 열 수 없습니다.\n{e}")
    
    # ========================================================================
    # 설정 창 (Settings Dialog)
    # ========================================================================
    
    def open_settings(self, icon=None, item=None):
        """
        설정 창을 엽니다.
        
        이미 열려 있다면 포커스만 이동시킵니다.
        """
        self.root.after(0, self._actual_open_settings)
    
    def _actual_open_settings(self):
        """
        실제 설정 창 생성 로직 (낮부 메서드, 메인 스레드 실행 필수)
        """
        try:
            if self.settings_window is None or not self.settings_window.winfo_exists():
                # 새 창 생성
                from view.dialogs.settings_dialog import SettingsDialog
                # 현재 열린 히스토리 창이 있으면 parent로 설정 (Z-order 문제 해결)
                parent = self.list_window if self.list_window and self.list_window.winfo_exists() else self.root
                self.settings_window = SettingsDialog(self.controller, parent=parent)
            else:
                # 기존 창 재사용 - 최상위로 올리기
                self.settings_window.lift()
                self.settings_window.focus_force()
        except Exception as e:
            self.logger.error(f"설정 창 열기 실패: {e}", exc_info=True)
            messagebox.showerror("오류", f"설정 창을 열 수 없습니다.\n{e}")
    
    # ========================================================================
    # 통계 창 (Statistics Dialog)
    # ========================================================================
    
    def open_statistics(self, icon=None, item=None):
        """
        통계 분석 창을 엽니다.
        
        통계 창은 매번 새로 생성합니다 (캐시하지 않음).
        """
        self.root.after(0, self._actual_open_statistics)
    
    def _actual_open_statistics(self):
        """
        실제 통계 창 생성 로직 (내부 메서드, 메인 스레드 실행 필수)
        """
        try:
            from view.dialogs.statistics_dialog import StatisticsDialog
            StatisticsDialog(self.controller)
        except Exception as e:
            self.logger.error(f"통계 창 열기 실패: {e}", exc_info=True)
            messagebox.showerror("오류", f"통계 창을 열 수 없습니다.\n{e}")
    
    # ========================================================================
    # 상세 조회 (Detail Popup)
    # ========================================================================
    
    def request_detail_popup(self, voc_id: str):
        """
        특정 VOC의 상세 정보를 표시하는 팝업 창을 엽니다.
        
        자동으로 읽음 처리를 수행합니다.
        
        Args:
            voc_id (str): VOC ID
        """
        try:
            # 읽음 처리
            self.controller.mark_as_read(voc_id)
            
            # 데이터 조회
            post = self.db.get_post_by_id(voc_id)
            if post:
                data = {k: post[k] for k in post.keys()}
                
                # 메인 스레드에서 실행
                from view.dialogs.detail_dialog import DetailDialog
                self.root.after(0, lambda: DetailDialog(self.controller, data))
            else:
                messagebox.showwarning("알림", "해당 게시글을 찾을 수 없습니다.")
        
        except DatabaseError as e:
            self.logger.error(f"상세 조회 실패 (ID: {voc_id}): {e.message}")
            messagebox.showerror("오류", f"상세 정보를 불러올 수 없습니다.\n{e.message}")
        except Exception as e:
            self.logger.error(f"상세 팝업 열기 실패: {e}", exc_info=True)
            messagebox.showerror("오류", f"상세 창을 열 수 없습니다.\n{e}")
