import customtkinter as ctk
from view.theme import theme_manager
from view.components.chips import ChipGroup

# -----------------------------------------------------------
# [신규] 편성 선택 팝업 (칩 그리드) - 이 클래스를 파일 상단에 두거나 별도 파일로 분리해도 됨
# -----------------------------------------------------------
class TrainSetSelector(ctk.CTkToplevel):
    def __init__(self, parent, max_set, current_val, callback):
        super().__init__(parent)
        self.callback = callback
        self.title("편성 선택")
        
        self.max_set = max_set # 부모로부터 전달받음

        # 윈도우 크기 계산 (10열 기준)
        rows = (self.max_set // 10) + 1
        h = rows * 45 + 50
        self.geometry(f"520x{h}")
        self.resizable(False, False)
        
        # 부모 중앙 배치
        if parent:
            self.transient(parent)
            try:
                x = parent.winfo_x() + (parent.winfo_width() // 2) - 260
                y = parent.winfo_y() + (parent.winfo_height() // 2) - (h // 2)
                self.geometry(f"+{x}+{y}")
            except: 
                pass
            
        self.attributes('-topmost', True)
        self.lift()
        self.focus_force()

        # 칩 컨테이너
        container = ctk.CTkFrame(self, fg_color="transparent")
        container.pack(fill="both", expand=True, padx=15, pady=15)

        # 현재 선택된 숫자 추출
        current_num = ''.join(filter(str.isdigit, str(current_val))) 
        
        # 그리드 생성
        for i in range(1, self.max_set + 1):
            row = (i - 1) // 10
            col = (i - 1) % 10
            
            is_selected = (str(i) == current_num)
            
            color = "#1F6AA5" if is_selected else "transparent"
            text_color = "white" if is_selected else ("black", "white")
            border_width = 0 if is_selected else 1
            
            btn = ctk.CTkButton(
                container, 
                text=f"{i}", 
                width=40, 
                height=35,
                fg_color=color,
                text_color=text_color,
                border_width=border_width,
                border_color=("gray60", "gray40"),
                hover_color="#144870",
                command=lambda val=i: self._on_select(val)
            )
            btn.grid(row=row, column=col, padx=3, pady=3)

    def _on_select(self, val):
        self.callback(f"{val}편성")
        self.destroy()

# -----------------------------------------------------------
# [수정] 메인 다이얼로그 클래스
# -----------------------------------------------------------
class ReportOptionDialog(ctk.CTkToplevel):
    def __init__(self, parent, controller, data, callback=None):
        super().__init__(parent)
        self.controller = controller
        self.data = data
        self.callback = callback
        
        self.title("보고서 생성 옵션")
        self.width = 600
        self.height = 750
        self._center_window()
        
        self.topmost_var = ctk.BooleanVar(value=True)
        self.attributes('-topmost', True)
        
        if parent:
            self.transient(parent)
        self.lift()
        self.focus_force()

        # 상단 제어 바
        self.control_bar = ctk.CTkFrame(self, fg_color="transparent")
        self.control_bar.pack(fill="x", padx=20, pady=(10, 0))
        
        self.topmost_check = ctk.CTkCheckBox(
            self.control_bar, text="항상 위", variable=self.topmost_var,
            command=self._toggle_topmost, font=theme_manager.get_font(12)
        )
        self.topmost_check.pack(side="right")
        
        # 로거 초기화
        from utils.logger import get_logger
        self.logger = get_logger("ReportOptionDialog")
        
        self.saved_opts = self.controller.settings.get('report_options', {})

        # 메인 스크롤 프레임
        self.scroll = ctk.CTkScrollableFrame(self)
        self.scroll.pack(fill="both", expand=True, padx=20, pady=20)
        
        # Config 로드
        self.config = self.load_config()

        # 0. VOC 추출 정보 (UI 레이아웃 대폭 수정)
        self.parsed = self._parse_voc_data()
        self._add_voc_extract_section()

        # 1. 사업소
        self._add_section("사업소 (Office)", "office", 
                          self.config.get("office_options", ["신평차량사업소"]))

        # 2. 팀
        self._add_section("소속 팀 (Team)", "team", 
                          self.config.get("team_options", ["검수1팀"]))
        
        # 3. 직위
        self._add_section("직위 (Position)", "position", 
                          self.config.get("position_options", ["사원"]))

        # 4. 보고자
        self._add_section("보고자 (Reporter)", "reporter_name", 
                          self.config.get("reporter_names", ["이대석"]), editable=True)

        # 5. 조치사항
        self._add_textbox("조치 사항 (Action Taken)", "action_taken")

        # 하단 버튼
        btn_frame = ctk.CTkFrame(self)
        btn_frame.pack(fill="x", pady=20, padx=20)
        
        ctk.CTkButton(btn_frame, text="생성 하기", command=self.on_submit).pack(side="right", padx=10)
        ctk.CTkButton(btn_frame, text="취소", command=self.destroy, fg_color="gray").pack(side="right", padx=10)

        self.chip_groups = {}
        self.inputs = {}

    def _add_voc_extract_section(self):
        """
        [수정됨] 호선 | 열번 | 편성 | 호차 가로 배치
        - 호선 변경 시 편성/호차 범위 자동 업데이트 기능 추가
        """
        p = self.parsed
        section = ctk.CTkFrame(self.scroll, fg_color="transparent")
        section.pack(fill="x", pady=(0, 10))

        ctk.CTkLabel(section, text="추출된 열차 정보", font=theme_manager.get_font(14, "bold")).pack(anchor="w", pady=(0, 8))

        # --- 통합 그룹 프레임 ---
        group_frame = ctk.CTkFrame(section, fg_color="transparent")
        group_frame.pack(fill="x", pady=(0, 5))
        for i in range(4): group_frame.columnconfigure(i, weight=1)

        headers = ["호선", "열번", "편성", "호차"]
        for i, h in enumerate(headers):
            ctk.CTkLabel(group_frame, text=h, font=theme_manager.get_font(12)).grid(row=0, column=i, sticky="w", padx=5, pady=(0, 2))

        # 1. 호선 (Line)
        self.voc_line_entry = ctk.CTkEntry(group_frame, height=32)
        self.voc_line_entry.grid(row=1, column=0, sticky="ew", padx=(0, 5))
        self.voc_line_entry.insert(0, p.get("line_str", ""))
        self.voc_line_entry.bind("<KeyRelease>", self._on_line_change) # 입력 시마다 감지

        # 2. 열번 (Train Num)
        candidates = p.get("train_candidates") or []
        train_str = str(p.get("train_str") or "").strip()
        combo_vals = sorted(list(set([str(c.get('train_number')) for c in candidates]))) if candidates else []
        if not combo_vals and train_str: combo_vals = [train_str]
        
        # 빈 값이 있을 경우를 위한 기본값
        if not combo_vals:
            combo_vals = [""]  # 빈 문자열을 기본 옵션으로
        
        self.voc_train_combo = ctk.CTkComboBox(group_frame, values=combo_vals, height=32)
        self.voc_train_combo.grid(row=1, column=1, sticky="ew", padx=5)
        
        # train_str이 있으면 설정, 없으면 빈 문자열 설정
        if train_str:
            self.voc_train_combo.set(train_str)
        else:
            self.voc_train_combo.set("")  # 명시적으로 빈 문자열 설정

        # 3. 편성 (Set) - 팝업 버튼 (Entry가 아님!)
        self.voc_set_var = ctk.StringVar(value=p.get("set_str", "1편성"))
        self.voc_set_btn = ctk.CTkButton(
            group_frame, 
            textvariable=self.voc_set_var,
            height=32,
            fg_color="transparent",
            border_width=1,
            border_color=("gray70", "gray30"),
            text_color=("black", "white"),
            command=self._open_set_popup
        )
        self.voc_set_btn.grid(row=1, column=2, sticky="ew", padx=5)

        # 4. 호차 (Car) - OptionMenu
        self.voc_car_menu = ctk.CTkOptionMenu(group_frame, values=["1호차"], height=32)
        self.voc_car_menu.grid(row=1, column=3, sticky="ew", padx=(5, 0))

        # --- 초기 UI 범위 설정 (최초 실행) ---
        self._update_ui_constraints(p.get("line_str", ""))
        
        # 추출된 호차 값 적용
        extracted_car = p.get("car_str", "").replace("호차", "").strip()
        if extracted_car and extracted_car.isdigit():
             self.voc_car_menu.set(f"{extracted_car}호차")


        # --- 열번 상세 후보군 (라디오 버튼) ---
        if candidates:
            radio_frame = ctk.CTkFrame(section, fg_color="transparent")
            radio_frame.pack(fill="x", pady=(10, 0))
            self.radio_var = ctk.StringVar(value=train_str)
            for c in candidates:
                dia = c.get('duty_id', '')
                num = str(c.get('train_number', ''))
                time_str = (c.get('time') or '')[:5]
                direction = "상행" if c.get('direction') == 'up' else "하행"
                label_text = f"{dia}다이아 {num}열차 ({time_str}) {direction}"
                rb = ctk.CTkRadioButton(
                    radio_frame, text=label_text, variable=self.radio_var, value=num,
                    font=theme_manager.get_font(12), command=self._on_radio_select
                )
                rb.pack(anchor="w", pady=2)

    def _on_radio_select(self):
        selected_num = self.radio_var.get()
        self.voc_train_combo.set(selected_num)

    def _on_line_change(self, event=None):
        """호선 입력값이 변경될 때마다 제한값 업데이트"""
        current_line = self.voc_line_entry.get()
        self._update_ui_constraints(current_line)

    def _update_ui_constraints(self, line_str):
        """
        호선 정보에 따라 최대 편성 수와 호차 목록을 갱신합니다.
        
        에러 처리:
        - get_line_spec 실패 시 기본값 사용
        - 사용자에게 별도 에러 표시 없음 (자연스러운 UX)
        """
        try:
            # ReportService의 Master Data 활용
            spec = self.controller.report_service.get_line_spec(line_str)
            self.current_max_set = spec.get("max_set", 56)  # 기본값: 2호선 기준
            self.current_max_car = spec.get("max_car", 8)   # 기본값: 최대치
        except Exception as e:
            # 에러 발생 시 기본값 사용 (사용자에게 에러 노출하지 않음)
            self.logger.warning(f"호선 정보 조회 실패: {e}, 기본값 사용")
            self.current_max_set = 56
            self.current_max_car = 8

        # 호차 메뉴 업데이트
        car_opts = [f"{i}호차" for i in range(1, self.current_max_car + 1)]
        
        current_val = self.voc_car_menu.get()
        self.voc_car_menu.configure(values=car_opts)
        
        if current_val not in car_opts:
            self.voc_car_menu.set(car_opts[0])

    def _open_set_popup(self):
        """편성 선택 팝업 오픈"""
        current_val = self.voc_set_var.get()
        TrainSetSelector(
            self, 
            max_set=self.current_max_set,
            current_val=current_val, 
            callback=lambda val: self.voc_set_var.set(val)
        )

    def on_submit(self):
        result = {}
        if hasattr(self, 'chip_fields'):
            for k, cg in self.chip_fields.items():
                val = cg.get()
                result[k] = val if val else ""
        
        if hasattr(self, 'input_fields'):
            for k, entry in self.input_fields.items():
                result[k] = entry.get()

        if hasattr(self, 'text_fields'):
            for k, tb in self.text_fields.items():
                result[k] = tb.get("1.0", "end-1c")

        # UI 값 가져오기
        if hasattr(self, 'voc_line_entry'):
            result['line_str'] = self.voc_line_entry.get().strip()
            
            # 열번 값 검증 - CTkComboBox 같은 위젯 이름 필터링
            train_num_raw = self.voc_train_combo.get().strip()
            if train_num_raw and not train_num_raw.startswith("CTk"):
                result['train_num'] = train_num_raw
            else:
                result['train_num'] = ""  # 빈 문자열로 설정
            
            result['train_set'] = self.voc_set_var.get().replace("편성", "").strip()
            result['car_str'] = self.voc_car_menu.get().replace("호차", "").strip()

        # 전화번호 매핑 등 기존 로직 수행
        tel_map = {
            "신평차량사업소": "200-5115",
            "노포차량사업소": "509-4380",
        }
        office = result.get('office', '')
        result['reporter_tel'] = tel_map.get(office, "000-0000")

        self.controller.save_report_options(result)
        
        if self.callback:
            self.callback(self.data, result)
            
        self.destroy()

    def load_config(self):
        return self.controller.settings.get('master_data', {})
    
    def _add_section(self, label_text, key, options, editable=False):
        # 기존 코드 그대로 유지
        header_frame = ctk.CTkFrame(self.scroll, fg_color="transparent")
        header_frame.pack(fill="x", pady=(15, 5))
        ctk.CTkLabel(header_frame, text=label_text, font=theme_manager.get_font(13, "bold")).pack(side="left")
        
        if editable:
            ctk.CTkButton(header_frame, text="+", width=24, height=24, 
                          command=lambda k=key: self._manage_chips(k, "add")).pack(side="left", padx=10)

        default_val = self.saved_opts.get(key, options[0] if options else None)
        cg = ChipGroup(
            self.scroll, options=options, default=default_val, multi_select=False,
            command_right=lambda val, k=key: self._manage_chips(k, "edit", val) if editable else None,
            command_double=lambda val, k=key: self._manage_chips(k, "edit", val) if editable else None
        )
        cg.pack(fill="x", pady=5)
        if not hasattr(self, 'chip_fields'): self.chip_fields = {}
        self.chip_fields[key] = cg

    def _manage_chips(self, key, action, val=None):
        # 기존 코드 그대로 유지
        current_options = self.config.get(key + "s", [])
        if key == "reporter_name": 
            list_key = "reporter_names"
            current_options = self.config.get(list_key, [])
        else: list_key = key + "s"

        if action == "add":
            dialog = ctk.CTkInputDialog(text="추가할 항목을 입력하세요:", title="항목 추가")
            dialog.geometry(f"+{self.winfo_x()+50}+{self.winfo_y()+100}")
            new_val = dialog.get_input()
            if new_val and new_val not in current_options:
                current_options.append(new_val)
                self._update_config_list(list_key, current_options)
                self.chip_fields[key].refresh(current_options)
        elif action == "edit" and val:
            self._open_edit_popup(list_key, key, val, current_options)

    def _open_edit_popup(self, list_key, key, old_val, options):
        # 기존 코드 그대로 유지 (팝업 로직)
        toplevel = ctk.CTkToplevel(self)
        toplevel.title("항목 수정")
        toplevel.geometry("300x150")
        toplevel.transient(self)
        toplevel.lift()
        toplevel.attributes('-topmost', True)
        tx = self.winfo_x() + (self.width//2) - 150
        ty = self.winfo_y() + (self.height//2) - 75
        toplevel.geometry(f"+{tx}+{ty}")

        ctk.CTkLabel(toplevel, text=f"'{old_val}' 수정", font=theme_manager.get_font(12, "bold")).pack(pady=10)
        entry = ctk.CTkEntry(toplevel)
        entry.pack(padx=20, pady=5, fill="x")
        entry.insert(0, old_val)

        btn_frame = ctk.CTkFrame(toplevel, fg_color="transparent")
        btn_frame.pack(pady=10, fill="x")

        def save_edit():
            new_val = entry.get()
            if new_val and new_val != old_val:
                idx = options.index(old_val)
                options[idx] = new_val
                self._update_config_list(list_key, options)
                self.chip_fields[key].refresh(options)
            toplevel.destroy()

        def delete_item():
            if old_val in options:
                options.remove(old_val)
                self._update_config_list(list_key, options)
                self.chip_fields[key].refresh(options)
            toplevel.destroy()

        ctk.CTkButton(btn_frame, text="수정", width=80, command=save_edit).pack(side="left", padx=10, expand=True)
        ctk.CTkButton(btn_frame, text="삭제", width=80, fg_color="red", hover_color="darkred", command=delete_item).pack(side="left", padx=10, expand=True)

    def _update_config_list(self, list_key, new_list):
        if 'master_data' not in self.controller.settings:
            self.controller.settings['master_data'] = {}
        self.controller.settings['master_data'][list_key] = new_list
        self.controller.save_settings()

    def _add_textbox(self, label_text, key):
        ctk.CTkLabel(self.scroll, text=label_text, font=theme_manager.get_font(13, "bold")).pack(anchor="w", pady=(15, 5))
        tb = ctk.CTkTextbox(self.scroll, height=100)
        tb.pack(fill="x", pady=5)
        tb.insert("1.0", self.saved_opts.get(key, "○ 해당 편성 점검 완료"))
        if not hasattr(self, 'text_fields'): self.text_fields = {}
        self.text_fields[key] = tb

    def _parse_voc_data(self):
        try:
            return self.controller.report_service._parse_voc_info(
                self.data.get("title", ""),
                self.data.get("content", ""),
                self.data.get("date", "")
            )
        except Exception:
            return {
                "line_str": "", "set_str": "", "car_str": "", "train_str": "",
                "train_details": {"type": "", "direction": ""},
                "train_candidates": []
            }
    
    def _center_window(self):
        self.update_idletasks()
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        x = (screen_width // 2) - (self.width // 2)
        y = (screen_height // 2) - (self.height // 2)
        y = max(0, y - 30)
        self.geometry(f"{self.width}x{self.height}+{x}+{y}")

    def _toggle_topmost(self):
        if self.winfo_exists():
            self.attributes('-topmost', self.topmost_var.get())

    def destroy(self):
        try: self.withdraw()
        except: pass
        super().destroy()