import customtkinter as ctk
from tkinter import ttk
import pystray
from PIL import Image, ImageDraw
import sys
import os

# winotify 사용 시도
try:
    from winotify import Notification, audio
    USE_WINOTIFY = True
except ImportError:
    from plyer import notification
    USE_WINOTIFY = False

class SettingsView(ctk.CTk):
    def __init__(self, controller):
        super().__init__()
        self.controller = controller
        self.title("VOC 모니터링 설정")
        self.geometry("500x500")
        
        self.tabview = ctk.CTkTabview(self)
        self.tabview.pack(padx=20, pady=20, fill="both", expand=True)
        
        self.tab_login = self.tabview.add("로그인")
        self.tab_crawl = self.tabview.add("크롤링 설정")
        self.tab_theme = self.tabview.add("테마")
        
        self._init_login_tab()
        self._init_crawl_tab()
        self._init_theme_tab()

    def _init_login_tab(self):
        ctk.CTkLabel(self.tab_login, text="사번 (ID)").pack(pady=5)
        self.entry_id = ctk.CTkEntry(self.tab_login)
        self.entry_id.pack(pady=5)
        self.entry_id.insert(0, self.controller.settings['login']['id'])
        
        ctk.CTkLabel(self.tab_login, text="비밀번호").pack(pady=5)
        self.entry_pw = ctk.CTkEntry(self.tab_login, show="*")
        self.entry_pw.pack(pady=5)
        self.entry_pw.insert(0, self.controller.settings['login']['pw'])

    def _init_crawl_tab(self):
        ctk.CTkLabel(self.tab_crawl, text="수집 주기 (분)").pack(pady=5)
        self.combo_interval = ctk.CTkComboBox(self.tab_crawl, values=["3", "5", "10", "15", "30"])
        self.combo_interval.pack(pady=5)
        self.combo_interval.set(str(self.controller.settings['crawling']['interval_minutes']))
        
        ctk.CTkLabel(self.tab_crawl, text="알림 키워드 (콤마로 구분)").pack(pady=5)
        self.entry_kw = ctk.CTkEntry(self.tab_crawl, width=300)
        self.entry_kw.pack(pady=5)
        self.entry_kw.insert(0, ",".join(self.controller.settings['crawling']['keywords']))

        ctk.CTkLabel(self.tab_crawl, text="관심 부서 (콤마로 구분)").pack(pady=5)
        self.entry_dept = ctk.CTkEntry(self.tab_crawl, width=300)
        self.entry_dept.pack(pady=5)
        self.entry_dept.insert(0, ",".join(self.controller.settings['crawling']['target_depts']))

        ctk.CTkButton(self.tab_crawl, text="설정 저장", command=self.save_all).pack(pady=20)

    def _init_theme_tab(self):
        ctk.CTkLabel(self.tab_theme, text="UI 테마 모드").pack(pady=10)
        self.combo_theme = ctk.CTkComboBox(self.tab_theme, values=["System", "Dark", "Light"])
        self.combo_theme.pack(pady=5)
        
        current_theme = self.controller.settings.get('theme', 'System')
        self.combo_theme.set(current_theme)
        
        ctk.CTkButton(self.tab_theme, text="테마 적용 및 저장", command=self.save_all).pack(pady=20)

    def save_all(self):
        self.controller.settings['login']['id'] = self.entry_id.get()
        self.controller.settings['login']['pw'] = self.entry_pw.get()
        self.controller.settings['crawling']['interval_minutes'] = int(self.combo_interval.get())
        self.controller.settings['crawling']['keywords'] = [k.strip() for k in self.entry_kw.get().split(',') if k.strip()]
        self.controller.settings['crawling']['target_depts'] = [k.strip() for k in self.entry_dept.get().split(',') if k.strip()]
        
        # 테마 저장 및 적용
        selected_theme = self.combo_theme.get()
        self.controller.settings['theme'] = selected_theme
        ctk.set_appearance_mode(selected_theme)
        
        self.controller.save_settings()
        self.controller.update_config_runtime()
        self.destroy()

class PreviewWindow(ctk.CTkToplevel):
    def __init__(self, controller, data):
        super().__init__()
        self.controller = controller
        self.data = data
        self.title("인쇄 미리보기")
        self.geometry("600x800")
        
        # 툴바
        toolbar = ctk.CTkFrame(self)
        toolbar.pack(fill="x", padx=10, pady=10)
        
        ctk.CTkButton(toolbar, text="🖨 인쇄하기", command=self._print).pack(side="left", padx=5)
        ctk.CTkButton(toolbar, text="💾 PDF 저장", command=self._save_pdf).pack(side="left", padx=5)
        ctk.CTkButton(toolbar, text="닫기", command=self.destroy, fg_color="gray").pack(side="right", padx=5)
        
        # A4 용지 느낌의 프레임 (흰색 고정)
        paper_frame = ctk.CTkFrame(self, fg_color="white") 
        paper_frame.pack(fill="both", expand=True, padx=20, pady=20)
        
        # 내용 표시 (텍스트 박스, 검은 글씨)
        self.text = ctk.CTkTextbox(paper_frame, text_color="black", fg_color="white", font=("Batang", 12))
        self.text.pack(fill="both", expand=True, padx=30, pady=30)
        
        self._render_content()
        self.text.configure(state="disabled")

    def _render_content(self):
        # 문서 양식 흉내
        d = self.data
        txt = f"""
[ VOC 상세 보고서 ]

■ 제  목 : {d['title']}
■ 부  서 : {d.get('department','-')}
■ 작성자 : {d.get('writer','-')}
■ 일  자 : {d.get('date','-')}
■ 상  태 : {d.get('status','-')}

=============================================================

[ 질의 내용 ]

{d.get('content','')}

=============================================================

[ 답변 내용 ]

{d.get('answer','')}
        """
        self.text.insert("1.0", txt)

    def _print(self):
        self.controller.request_print_voc(self.data)
        
    def _save_pdf(self):
        self.controller.request_create_pdf(self.data)

class VOCDetailView(ctk.CTkToplevel):
    """VOC 상세 정보를 보여주는 별도의 창"""
    def __init__(self, controller, data):
        super().__init__()
        self.controller = controller
        self.data = data
        self.title(f"VOC 상세 정보 - {data['title']}")
        self.geometry("900x900")
        self.attributes('-topmost', True)
        
        # ESC 키 바인딩
        self.bind("<Escape>", lambda e: self.destroy())

        # 전체 컨테이너
        self.main_container = ctk.CTkFrame(self)
        self.main_container.pack(fill="both", expand=True, padx=20, pady=20)

        # 1. 메인 정보 그룹 (상단)
        self._create_info_section(self.main_container, data)
        
        # 구분선
        ctk.CTkFrame(self.main_container, height=2, fg_color="gray50").pack(fill="x", pady=10)

        # 2. 상세 정보 그룹 (중앙)
        self.content_frame = ctk.CTkFrame(self.main_container, fg_color="transparent")
        self.content_frame.pack(fill="both", expand=True)
        
        # 2-1. 제목
        ctk.CTkLabel(self.content_frame, text=data['title'], font=("Malgun Gothic", 18, "bold"), anchor="w").pack(fill="x", pady=(0, 10))
        
        # 2-2. 처리부서 / 역명
        sub_info_frame = ctk.CTkFrame(self.content_frame, fg_color="transparent")
        sub_info_frame.pack(fill="x", pady=(0, 10))
        ctk.CTkLabel(sub_info_frame, text=f"처리부서: {data.get('department', '-')}", font=("Malgun Gothic", 14), anchor="w").pack(side="left", padx=(0, 20))
        ctk.CTkLabel(sub_info_frame, text=f"역명: {data.get('station', '-')}", font=("Malgun Gothic", 14), anchor="w").pack(side="left")

        # 2-3. 질의내용 (가장 큰 영역 차지)
        ctk.CTkLabel(self.content_frame, text="<질의 내용>", font=("Malgun Gothic", 12, "bold"), anchor="w").pack(fill="x")
        self.q_text = ctk.CTkTextbox(self.content_frame, font=("Malgun Gothic", 14), height=300)
        self.q_text.pack(fill="both", expand=True, pady=(5, 10))
        self.q_text.insert("1.0", str(data.get('content', '')))
        self.q_text.configure(state="disabled")

        # 2-4. 고객 첨부파일
        file_frame = ctk.CTkFrame(self.content_frame)
        file_frame.pack(fill="x", pady=(0, 10))
        ctk.CTkLabel(file_frame, text="첨부파일:", width=80, anchor="w").pack(side="left", padx=10)
        
        # NoneType 처리 강화
        att_val = data.get('attachment')
        att_text = str(att_val).strip() if att_val else ""
        if not att_text: att_text = "없음"
        
        # text_color 오류 수정: "text_color"라는 색상 이름은 없음. 
        # 파일이 있으면 blue, 없으면 기본값(None 혹은 시스템 테마 따름).
        text_col = "blue" if att_text != "없음" else ("gray90", "gray10") # (light, dark) 테마 대응
        
        self.lbl_att = ctk.CTkLabel(file_frame, text=att_text, anchor="w", text_color=text_col)
        self.lbl_att.pack(side="left", fill="x", expand=True, padx=5)
        
        # TODO: 실제 파일 다운로드 로직 연결 필요 (현재는 표시만)
        if att_text != "없음":
             self.lbl_att.bind("<Button-1>", lambda e: self._open_file(att_text))
             self.lbl_att.configure(cursor="hand2")

        # 2-5. 답변내용 (질의내용보다 작게)
        ctk.CTkLabel(self.content_frame, text="<답변 내용>", font=("Malgun Gothic", 12, "bold"), anchor="w").pack(fill="x")
        self.a_text = ctk.CTkTextbox(self.content_frame, font=("Malgun Gothic", 14), height=150)
        self.a_text.pack(fill="x", pady=(5, 10))
        self.a_text.insert("1.0", str(data.get('answer', '')))
        self.a_text.configure(state="disabled")

        # 3. 하단 버튼 그룹
        btn_frame = ctk.CTkFrame(self.main_container, fg_color="transparent")
        btn_frame.pack(fill="x", pady=10)
        
        # [수정] 컨트롤러에게 위임 -> 미리보기 창 열기
        ctk.CTkButton(btn_frame, text="미리보기/인쇄", width=120, 
                      command=self._open_preview).pack(side="left", padx=5)
                      
        ctk.CTkButton(btn_frame, text="보고서생성(Hwp)", width=120, 
                      command=lambda: self.controller.request_create_report(self.data)).pack(side="left", padx=5)
                      
        ctk.CTkButton(btn_frame, text="닫기 (ESC)", width=100, command=self.destroy, fg_color="gray").pack(side="right")

    def _open_preview(self):
        PreviewWindow(self.controller, self.data)

    def _create_info_section(self, parent, data):
        info_frame = ctk.CTkFrame(parent)
        info_frame.pack(fill="x")
        
        # Grid 설정
        info_frame.columnconfigure((0,1,2,3,4), weight=1)
        
        # 1행: 번호, 접수채널, 등록일자, VOC유형+요약? -> VOC유형까지
        items_row1 = [
            ("접수번호", data['id']),
            ("접수채널", data.get('channel', '-')),
            ("등록일자", data.get('date', '-')),
            ("VOC유형", data.get('voc_type', '-'))
        ]
        
        for idx, (label, val) in enumerate(items_row1):
            self._add_info_item(info_frame, idx, 0, label, val)

        # 2행: 응답구분, 작성자, 처리부서, 상태, 공개여부
        is_pub = "공개" if data.get('is_public') else "비공개"
        items_row2 = [
            ("응답구분", data.get('response_type', '-')),
            ("작성자", data['writer']),
            ("처리부서", data['department']),
            ("상태", data['status']),
            ("공개여부", is_pub)
        ]

        for idx, (label, val) in enumerate(items_row2):
            self._add_info_item(info_frame, idx, 1, label, val)

    def _add_info_item(self, parent, col, row, label, value):
        f = ctk.CTkFrame(parent, fg_color="transparent")
        f.grid(row=row, column=col, padx=5, pady=5, sticky="ew")
        
        ctk.CTkLabel(f, text=label, font=("Malgun Gothic", 11), text_color="gray70").pack(anchor="w")
        ctk.CTkLabel(f, text=str(value), font=("Malgun Gothic", 12, "bold")).pack(anchor="w")

    def _open_file(self, filename):
        """파일 열기 시도 (경로는 추후 구현 필요, 현재는 알림만)"""
        # 실제 로컬 경로가 있다면 os.startfile(path) 등을 사용
        print(f"파일 열기 클릭: {filename}")
        # 임시 알림
        try:
            from tkinter import messagebox
            messagebox.showinfo("알림", f"파일 다운로드 기능은 구현 중입니다.\n파일명: {filename}")
        except: pass

class VOCListView(ctk.CTkToplevel):
    def __init__(self, controller, data_rows):
        super().__init__()
        self.controller = controller
        self.title("VOC 수집 내역")
        self.geometry("1000x600")
        self.all_data = data_rows # 필터링용 원본 데이터
        
        # --- 상단: 필터 및 검색 레이아웃 ---
        self.filter_frame = ctk.CTkFrame(self)
        self.filter_frame.pack(fill="x", padx=20, pady=10)
        
        ctk.CTkLabel(self.filter_frame, text="검색어 필터:").pack(side="left", padx=10)
        self.search_entry = ctk.CTkEntry(self.filter_frame, width=300, placeholder_text="제목, 내용, 부서 검색...")
        self.search_entry.pack(side="left", padx=10)
        self.search_entry.bind("<KeyRelease>", lambda e: self.apply_filter())

        self.btn_refresh = ctk.CTkButton(self.filter_frame, text="새로고침", width=100, command=self.refresh_and_update)
        self.btn_refresh.pack(side="right", padx=10)

        # --- 메인: 트리뷰 목록 ---
        self.list_frame = ctk.CTkFrame(self)
        self.list_frame.pack(fill="both", expand=True, padx=20, pady=10)
        
        # 스크롤바 추가
        self.tree_scroll = ttk.Scrollbar(self.list_frame)
        self.tree_scroll.pack(side="right", fill="y")

        # 컬럼 정의: 번호, 제목, 처리부서, 상태, 접수채널, 고객명, 공개여부
        columns = ("번호", "제목", "처리부서", "상태", "접수채널", "고객명", "공개여부")
        
        self.tree = ttk.Treeview(
            self.list_frame, 
            columns=columns, 
            show='headings', 
            yscrollcommand=self.tree_scroll.set,
            style="Custom.Treeview"
        )
        self.tree_scroll.config(command=self.tree.yview)

        # 헤더 설정 및 정렬 연결
        for col in columns:
            self.tree.heading(col, text=col, command=lambda c=col: self.sort_column(c, False))
            self.tree.column(col, anchor="center")

        # 컬럼 너비 설정
        self.tree.column("제목", width=500, anchor="w")
        self.tree.column("번호", width=100)
        self.tree.column("공개여부", width=80)
        self.tree.column("접수채널", width=100)
        self.tree.column("고객명", width=100)
        
        self.tree.pack(fill="both", expand=True)
        self.tree.bind("<Double-1>", self._on_double_click)

        # 데이터 초기 삽입
        self.update_data(data_rows)
    
    def refresh_and_update(self):
        # controller의 run_cycle을 스레드로 실행하여 UI 멈춤 방지
        import threading
        t = threading.Thread(target=self.controller.run_cycle, daemon=True)
        t.start()

    def update_data(self, rows):
        """데이터 갱신 및 내림차순 정렬 적용"""
        self.all_data = rows
        self.apply_filter()

    def apply_filter(self):
        """현재 검색어에 따라 필터링하여 목록 표시"""
        query = self.search_entry.get().lower()
        for i in self.tree.get_children():
            self.tree.delete(i)
            
        filtered = [
            r for r in self.all_data 
            if query in r['title'].lower() or query in r['department'].lower() or query in r['writer'].lower()
        ]
        
        # 정렬 (기본: 번호 내림차순)
        # 단, 정렬 기준 컬럼이 변경되었을 수 있으므로 이 부분은 
        # 처음 로딩 시나 명시적 정렬 시에만 적용되도록 함이 좋으나,
        # 유저가 "번호 기준 내림차순 정렬"을 명시했으므로 기본값으로 둔다.
        # 단, 사용자가 컬럼 클릭으로 정렬을 바꿨다면 그 상태를 유지해야 하는데 복잡해지므로
        # 여기서는 매 필터링마다 최신순(번호 역순)으로 보여준다.
        try:
            filtered.sort(key=lambda x: int(x['id']), reverse=True)
        except:
             filtered.sort(key=lambda x: str(x['id']), reverse=True)

        for row in filtered:
            is_pub = "공개" if row.get('is_public') else "비공개"
            
            self.tree.insert("", "end", values=(
                row['id'], 
                row['title'], 
                row['department'], 
                row['status'], 
                row.get('channel', '-'), 
                row.get('writer', '-'), 
                is_pub
            ))

    def sort_column(self, col, reverse):
        """컬럼 헤더 클릭 시 데이터 정렬"""
        l = [(self.tree.set(k, col), k) for k in self.tree.get_children('')]
        # 숫자 정렬 시도 (번호 등)
        try:
            l.sort(key=lambda t: int(t[0]), reverse=reverse)
        except ValueError:
            l.sort(reverse=reverse)

        for index, (val, k) in enumerate(l):
            self.tree.move(k, '', index)

        self.tree.heading(col, command=lambda: self.sort_column(col, not reverse))

    def _on_double_click(self, event):
        selected = self.tree.selection()
        if not selected: return
        # 첫 번째 컬럼(번호)이 ID임
        voc_id = self.tree.item(selected[0])['values'][0]
        self.controller.request_detail_popup(voc_id)

class NotificationView(ctk.CTkToplevel):
    """우측 하단에 나타나는 커스텀 알림 창"""
    def __init__(self, controller, title, msg, voc_id=None):
        super().__init__()
        self.controller = controller
        self.voc_id = voc_id
        
        # 1. 창 설정 (타이틀바 없음, 최상위)
        self.overrideredirect(True)
        self.attributes('-topmost', True)
        self.title("VOC 알림")
        
        # 2. 디자인 및 레이아웃
        self.configure(fg_color="#333333") # 다크 모드 배경
        
        # 메인 컨테이너
        container = ctk.CTkFrame(self, fg_color="transparent")
        container.pack(fill="both", expand=True, padx=15, pady=15)
        
        # 제목
        ctk.CTkLabel(
            container, 
            text=title, 
            font=("Roboto", 14, "bold"), 
            text_color="#3B8ED0" # 포인트 컬러
        ).pack(anchor="w", pady=(0, 5))
        
        # 내용
        ctk.CTkLabel(
            container, 
            text=msg, 
            wraplength=280, 
            justify="left",
            font=("Roboto", 12)
        ).pack(anchor="w")
        
        # 클릭 이벤트 바인딩 (전체 영역)
        for widget in [self, container] + container.winfo_children():
            widget.bind("<Button-1>", self._on_click)
            widget.bind("<Enter>", lambda e: self.configure(cursor="hand2"))
            widget.bind("<Leave>", lambda e: self.configure(cursor=""))

        # 3. 위치 지정 (우측 하단)
        self.update_idletasks()
        w, h = 320, 100 # 기본 크기
        screen_w = self.winfo_screenwidth()
        screen_h = self.winfo_screenheight()
        # 작업 표시줄 높이 대략 고려 (40~50px)
        x = screen_w - w - 20
        y = screen_h - h - 60
        self.geometry(f"{w}x{h}+{x}+{y}")
        
        # 4. 자동 종료 예약
        self.after(5000, self.destroy)
        
    def _on_click(self, event):
        """알림 클릭 시 상세 정보 열기"""
        if self.voc_id:
            self.controller.request_detail_popup(self.voc_id)
        self.destroy()

class SystemTray:
    def __init__(self, controller):
        self.controller = controller
        self.icon = None

    def create_modern_icon(self):
        w, h = 64, 64
        image = Image.new('RGBA', (w, h), (0, 0, 0, 0))
        dc = ImageDraw.Draw(image)
        dc.ellipse((4, 4, 60, 60), fill=(58, 123, 213))
        dc.line((20, 32, 30, 42), fill="white", width=4)
        dc.line((30, 42, 44, 22), fill="white", width=4)
        return image

    def run(self, on_check, on_list, on_settings, on_quit):
        menu = (
             pystray.MenuItem('VOC 모니터링 열기', lambda *args: on_list()), # 메인 기능
             pystray.Menu.SEPARATOR,
             pystray.MenuItem('지금 확인', lambda *args: on_check()),
             pystray.MenuItem('설정', lambda *args: on_settings()),
             pystray.MenuItem('종료', lambda *args: on_quit()),
        )
        self.icon = pystray.Icon("VOC_Monitor", self.create_modern_icon(), "VOC 알리미", menu)
        self.icon.run()

    def stop(self):
        if self.icon:
            self.icon.stop()

    def show_notification(self, title, msg, voc_id=None):
        """커스텀 알림 창 표시 (메인 스레드에서 실행)"""
        # controller.root.after를 사용하여 메인 스레드에서 UI 생성 보장
        self.controller.root.after(0, lambda: NotificationView(self.controller, title, msg, voc_id))
