"""
보고서 처리 관리자 (Report Manager)

AppController의 보고서 생성, 인쇄, PDF 변환 로직을 전담합니다.
사용자의 보고서 생성 요청을 받아 ReportService를 호출하고,
결과를 UI에 표시하는 중재자 역할을 수행합니다.

주요 기능:
    - 보고서 생성 요청 처리
    - 기존 파일 존재 시 사용자 선택 다이얼로그
    - 부분 실패 에러 처리 (열차번호 조회 실패 등)
    - HWP 인쇄 기능
    - PDF 변환 기능

아키텍처:
    AppController
    ├── ReportManager (보고서 처리)
    │   └── ReportService (실제 생성)
    └── ...

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

from core.exceptions import ReportError, is_partial_failure


class ReportManager:
    """
    보고서 생성 및 처리 관리자
    
    보고서 생성, 인쇄, PDF 변환 등의 모든 보고서 관련 작업을 처리합니다.
    에러 처리와 사용자 피드백을 포함하여 안정적인 보고서 생성을 보장합니다.
    
    Attributes:
        controller: AppController 인스턴스 (의존성 주입)
        report_service: ReportService 인스턴스
        logger: 로거 인스턴스
        root: Tkinter 루트 윈도우
        settings: 설정 딕셔너리
    
    주요 메서드:
        request_create_report: 보고서 생성 요청 진입점
        request_print_voc: 인쇄 요청
        request_create_pdf: PDF 생성 요청
    
    사용 예시:
        >>> report_mgr = ReportManager(controller)
        >>> report_mgr.request_create_report(voc_data, parent_window)
    """
    
    def __init__(self, controller):
        """
        ReportManager 초기화
        
        Args:
            controller (AppController): 메인 컨트롤러 인스턴스
        """
        self.controller = controller
        self.report_service = controller.report_service
        self.logger = controller.logger
        self.root = controller.root
        self.settings = controller.settings
    
    # ========================================================================
    # 보고서 생성 (Report Generation)
    # ========================================================================
    
    def request_create_report(self, data: dict, parent=None):
        """
        보고서 생성 요청을 받아 옵션 다이얼로그를 엽니다.
        
        역명 정보를 기반으로 기본 사업소를 유추하고,
        사용자가 옵션을 선택하면 실제 생성 로직을 실행합니다.
        
        Args:
            data (dict): VOC 데이터
                - id: VOC ID
                - title: 제목
                - content: 내용
                - date: 날짜
                - department: 부서
                - station (optional): 역명
            parent (Widget, optional): 부모 윈도우
        
        Raises:
            Exception: 다이얼로그 생성 실패 시
        """
        try:
            # 역명에 따른 기본 사업소 유추
            station = data.get('station', '')
            if station:
                if any(x in station for x in ["신평", "다대포", "중앙", "부산역"]):
                    data['office'] = "신평차량사업소"
                elif any(x in station for x in ["노포", "범어사", "동래", "연산"]):
                    data['office'] = "노포차량사업소"
            
            # 콜백 함수: 다이얼로그에서 '생성'을 누르면 실행
            def actual_generate(data, options):
                self._generate_report_with_options(data, options, parent)
            
            from view.dialogs.report_option_dialog import ReportOptionDialog
            target_parent = parent if parent else self.root
            ReportOptionDialog(target_parent, self.controller, data, callback=actual_generate)
        
        except Exception as e:
            self.logger.error(f"보고서 생성 요청 실패: {e}", exc_info=True)
            messagebox.showerror("오류", f"보고서 생성을 시작할 수 없습니다.\n{e}")
    
    def _generate_report_with_options(self, data: dict, options: dict, parent):
        """
        보고서 생성 실행 (내부 메서드)
        
        사용자가 선택한 옵션을 데이터에 병합하고,
        ReportService를 호출하여 HWP 보고서를 생성합니다.
        
        에러 처리:
            - 부분 실패 (열차번호 조회 실패): 경고만 표시하고 계속
            - 전체 실패 (템플릿 없음 등): 에러 표시 및 중단
            - 기존 파일 존재: 사용자 선택 다이얼로그 표시
        
        Args:
            data (dict): VOC 데이터
            options (dict): 보고서 옵션
                - office: 사업소
                - team: 팀
                - reporter_name: 보고자
                - position: 직위
                - action_taken: 조치사항
            parent (Widget): 부모 윈도우
        """
        try:
            # 사업소별 전화번호 매핑
            tel_map = self.settings.get('master_data', {}).get('office_tel_map', {})
            office = options.get('office', '')
            options['reporter_tel'] = tel_map.get(office, "000-0000")
            
            # 옵션을 데이터에 병합
            data.update(options)
            
            # ReportService 호출
            result = self.report_service.create_hwp_report(data)
            
            # 결과 처리
            if isinstance(result, tuple) and len(result) == 2:
                status, msg_or_path = result
                
                if status == "FILE_EXISTS":
                    # 기존 파일 존재
                    self._handle_existing_report(msg_or_path, data, parent)
                elif status:
                    # 정상 생성 완료
                    file_path = msg_or_path.split('\n')[1] if '\n' in msg_or_path else msg_or_path
                    from view.dialogs.report_complete_dialog import ReportCompleteDialog
                    self.root.after(1000, lambda: ReportCompleteDialog(parent, file_path))
                else:
                    # 생성 실패
                    messagebox.showerror("보고서 생성 실패", msg_or_path)
            else:
                messagebox.showerror("오류", "예상치 못한 응답 형식입니다.")
        
        except ReportError as e:
            if is_partial_failure(e):
                # 부분 실패: 경고만 표시하고 계속
                self.logger.warning(f"부분 실패: {e.message}")
                messagebox.showwarning("경고", e.message)
            else:
                # 전체 실패
                self.logger.error(f"보고서 생성 실패: {e.message}")
                messagebox.showerror("오류", e.message)
        except Exception as e:
            self.logger.error(f"보고서 생성 중 오류: {e}", exc_info=True)
            messagebox.showerror("오류", f"보고서 생성 중 오류가 발생했습니다.\n{e}")
    
    def _handle_existing_report(self, file_path: str, data: dict, parent):
        """
        기존 보고서 존재 시 사용자 선택 처리 (내부 메서드)
        
        사용자에게 3가지 선택지를 제공합니다:
            - 예: 기존 파일 열기
            - 아니오: 새로 생성 (기존 파일 덮어쓰기)
            - 취소: 작업 취소
        
        Args:
            file_path (str): 기존 파일 경로
            data (dict): VOC 데이터
            parent (Widget): 부모 윈도우
        """
        from tkinter import messagebox as mb
        
        choice = mb.askyesnocancel(
            "기존 보고서 발견",
            f"동일한 보고서가 이미 존재합니다:\n\n{file_path}\n\n"
            "• 예: 기존 파일 열기\n"
            "• 아니오: 새로 생성 (기존 파일 덮어쓰기)\n"
            "• 취소: 작업 취소"
        )
        
        if choice is True:
            # 기존 파일 열기
            os.startfile(file_path)
            from view.dialogs.report_complete_dialog import ReportCompleteDialog
            self.root.after(500, lambda: ReportCompleteDialog(parent, file_path))
        elif choice is False:
            # 새로 생성 (강제 덮어쓰기)
            try:
                os.remove(file_path)
                success2, msg2 = self.report_service.create_hwp_report(data)
                if success2:
                    file_path2 = msg2.split('\n')[1] if '\n' in msg2 else msg2
                    from view.dialogs.report_complete_dialog import ReportCompleteDialog
                    self.root.after(1000, lambda: ReportCompleteDialog(parent, file_path2))
                else:
                    messagebox.showerror("보고서 생성 실패", msg2)
            except Exception as e:
                messagebox.showerror("오류", f"파일 삭제 실패: {e}")
        # choice is None (취소): 아무것도 하지 않음
    
    # ========================================================================
    # 인쇄 및 PDF (Print & PDF)
    # ========================================================================
    
    def request_print_voc(self, data: dict):
        """
        인쇄 요청을 받아 ReportService 호출
        
        Windows 기본 프린터로 VOC 상세 내용을 출력합니다.
        
        Args:
            data (dict): 인쇄할 VOC 데이터
                - id: VOC ID
                - title: 제목
                - content: 내용
                - answer: 답변 (optional)
        
        Raises:
            ReportError: 인쇄 실패 시
        """
        try:
            success, msg = self.report_service.print_voc_detail(data)
            if success:
                messagebox.showinfo("인쇄 성공", msg)
            else:
                messagebox.showerror("인쇄 실패", msg)
        except ReportError as e:
            self.logger.error(f"인쇄 실패: {e.message}")
            messagebox.showerror("오류", e.message)
        except Exception as e:
            self.logger.error(f"인쇄 중 오류: {e}", exc_info=True)
            messagebox.showerror("오류", f"인쇄 중 오류가 발생했습니다.\n{e}")
    
    def request_create_pdf(self, data: dict):
        """
        PDF 생성 요청을 받아 ReportService 호출
        
        VOC 데이터를 PDF 형식으로 변환하여 저장합니다.
        
        Args:
            data (dict): VOC 데이터
                - id: VOC ID
                - title: 제목
                - content: 내용
                - date: 날짜
                - department: 부서
        
        Raises:
            ReportError: PDF 생성 실패 시
        """
        try:
            success, msg = self.report_service.create_pdf_report(data)
            if success:
                messagebox.showinfo("PDF 생성 성공", msg)
            else:
                messagebox.showerror("PDF 생성 실패", msg)
        except ReportError as e:
            self.logger.error(f"PDF 생성 실패: {e.message}")
            messagebox.showerror("오류", e.message)
        except Exception as e:
            self.logger.error(f"PDF 생성 중 오류: {e}", exc_info=True)
            messagebox.showerror("오류", f"PDF 생성 중 오류가 발생했습니다.\n{e}")
