from PySide6.QtWidgets import (QDialog, QFileDialog, QVBoxLayout, QHBoxLayout, QGridLayout, QTreeWidget, QTreeWidgetItem, QLabel, QLineEdit, QPushButton,
                               QSpinBox, QGroupBox, QFileDialog, QMessageBox, QComboBox)
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont, QColor
import sqlite3
import shutil
import os, re
import pandas as pd

class CMBSettingsDialog(QDialog):
    def __init__(self, parent=None, logger=None, debug=False):
        super().__init__(parent)
        self.setWindowTitle("CMB 설정")
        self.resize(900, 600)

        self.logger = logger
        self.debug = debug
        # DB 파일 경로 설정
        self.user_db_path = os.path.join("src", "userDB.db")
        self.initial_db_path = os.path.join("src", "initialDB.db")

        # userDB 체크 및 초기화
        if not os.path.exists(self.user_db_path):
            shutil.copyfile(self.initial_db_path, self.user_db_path)
            
        # DB 연결 설정
        self.conn = sqlite3.connect(self.user_db_path)
        self.cursor = self.conn.cursor()

        # 메인 레이아웃 설정
        main_layout = QHBoxLayout()
        
        left_layout = QVBoxLayout()
        mid_layout = QVBoxLayout()        
        self.right_layout = QVBoxLayout()
        

        # 카테고리 검색 및 단계 설정 버튼
        search_layout = QGridLayout()
        search_layout.addWidget(QLabel("카테고리 검색:"),0,0,1,1)
        self.search_input = QLineEdit()
        self.search_input.returnPressed.connect(self.search_category)
        self.search_btn = QPushButton("검색")
        self.search_btn.setDefault(True)
        self.search_btn.setAutoDefault(True)
        self.search_btn.setDefault(False)

        self.search_btn.clicked.connect(self.search_category)
        search_layout.addWidget(self.search_input,0,1,1,3)
        search_layout.addWidget(self.search_btn,0,2,1,1)
        self.cmb_view_btn = QPushButton("모두 보기")
        self.cmb_view_btn.clicked.connect(self.toggle_cmb_view)
        search_layout.addWidget(self.cmb_view_btn,0,3,1,1)


        # 1레벨, 2레벨, 3레벨 콤보박스와 라벨 설정
        self.level1_combo = QComboBox()
        self.level2_combo = QComboBox()
        self.level3_combo = QComboBox()
        self.reset_combo_btn = QPushButton("콤보리셋")

        # 기본적으로 "모두 보기" 옵션 추가
        self.level1_combo.addItem("모두 보기")
        self.level2_combo.addItem("모두 보기")
        self.level3_combo.addItem("모두 보기")

        # 레벨 필터링 라벨 추가
        # search_layout.addWidget(QLabel("1레벨:"))
        search_layout.addWidget(self.level1_combo,1,1,1,2)
        # search_layout.addWidget(QLabel("2레벨:"))
        search_layout.addWidget(self.level2_combo,1,2,1,2)
        # search_layout.addWidget(QLabel("3레벨:"))
        search_layout.addWidget(self.level3_combo,1,3,1,2)
        search_layout.addWidget(self.level3_combo,1,3,1,2)
        search_layout.addWidget(self.reset_combo_btn,1,4,1,1)

        # 콤보박스의 신호 연결
        self.level1_combo.currentTextChanged.connect(self.update_level2_combo)
        self.level1_combo.currentTextChanged.connect(self.filter_category_tree)
        self.level2_combo.currentTextChanged.connect(self.update_level3_combo)
        self.level2_combo.currentTextChanged.connect(self.filter_category_tree)
        self.level3_combo.currentTextChanged.connect(self.filter_category_tree)

        # 콤보박스 리셋
        self.reset_combo_btn.clicked.connect(self.reset_comboboxes)

        # # 카테고리 레벨별 필터링을 위한 콤보박스
        # filter_label = QLabel("카테고리 필터:")
        # filter_combo = QComboBox()
        # filter_combo.addItem("모두 보기")
        # filter_combo.addItem("Level 1")
        # filter_combo.addItem("Level 2")
        # filter_combo.addItem("Level 3")
        # filter_combo.addItem("Level 4")
        # filter_combo.currentIndexChanged.connect(self.filter_categories)
        # search_layout.addWidget(filter_label,1,0,1,1)
        # search_layout.addWidget(filter_combo)


        left_layout.addLayout(search_layout, 1)
        
        # 카테고리 목록 테이블
        self.category_tree = QTreeWidget()
        self.category_tree.setHeaderLabels(["ID", "Level1", "Level2", "Level3", "Level4", "CMB 단계"])
        self.category_tree.setColumnCount(6)
        self.category_tree.setRootIsDecorated(False)
        self.category_tree.setAlternatingRowColors(True)
        self.category_tree.setSortingEnabled(True)  # 정렬 기능 활성화
        # 정렬 순서 추적
        self.sort_order = Qt.AscendingOrder

        # 헤더 클릭 시그널 연결
        self.category_tree.header().sectionClicked.connect(self.sort_by_column)

        left_layout.addWidget(self.category_tree, 6)
        main_layout.addLayout(left_layout,7)
        
        if self.debug:

            # DB 생성 및 초기화 버튼 추가
            db_create_btn = QPushButton("DB 생성")
            db_create_btn.clicked.connect(self.create_tables)
            db_reset_btn = QPushButton("DB 초기화")
            db_reset_btn.clicked.connect(self.reset_db)
            mid_layout.addWidget(db_create_btn)
            mid_layout.addWidget(db_reset_btn)

        # 단계별 적용 버튼 추가
        apply_1_btn = QPushButton("1단계 적용")
        apply_2_btn = QPushButton("2단계 적용")
        apply_3_btn = QPushButton("3단계 적용")
        remove_cmb_stage_button = QPushButton("선택 CMB 해제")

        self.select_toggle_button = QPushButton("전체 선택")

        apply_1_btn.clicked.connect(lambda: self.apply_crmobi_stage(1))
        apply_2_btn.clicked.connect(lambda: self.apply_crmobi_stage(2))
        apply_3_btn.clicked.connect(lambda: self.apply_crmobi_stage(3))
        remove_cmb_stage_button.clicked.connect(self.remove_cmb_stage)
        self.select_toggle_button.clicked.connect(self.toggle_select_all_filtered_items)

        mid_layout.addWidget(apply_1_btn)
        mid_layout.addWidget(apply_2_btn)
        mid_layout.addWidget(apply_3_btn)
        mid_layout.addWidget(remove_cmb_stage_button)
        mid_layout.addWidget(self.select_toggle_button)

        # 닫기 버튼
        close_btn = QPushButton("닫기")
        close_btn.clicked.connect(self.close)
        mid_layout.addWidget(close_btn)
        
        # CMB 단계 설정 표시/숨기기 버튼
        toggle_button = QPushButton("CMB 단계 설정 ▶")
        toggle_button.setCheckable(True)
        toggle_button.clicked.connect(self.toggle_cmb_settings)
        mid_layout.addWidget(toggle_button)

        main_layout.addLayout(mid_layout,1)

        # CMB 단계 설정 그룹 추가
        self.cmb_settings_group = QGroupBox("CMB 단계 설정")

        cmb_settings_layout = QVBoxLayout()
        
        # CMB 단계를 설정 후 저장하는 버튼
        save_cmb_stage_button = QPushButton("CMB 단계 저장")
        save_cmb_stage_button.clicked.connect(self.save_cmb_stage_to_db)
        cmb_settings_layout.addWidget(save_cmb_stage_button)

        # 각 단계별 설정
        self.stage_widgets = []
        for i in range(1, 4):
            stage_group_box = QGroupBox(f"{i}단계")
            stage_group_box_layout = QGridLayout()
            
            # CustomSpinBox로 대체
            min_amount_label = QLabel("원 초과시")
            min_amount_label.setStyleSheet("""
                QLabel {
                    font-size: 12pt;       /* 폰트 크기 설정 */
                    font-weight: bold;     /* 굵은 폰트 */
                    font-style: normal;    /* 기울임 없음 */
                }
            """)
            min_amount_spin = CustomSpinBox()
            min_amount_spin.setSuffix ("₩")
            min_amount_spin.setValue(100000 * i)
            min_amount_spin.setSingleStep(1000)

            unit_amount_label = QLabel("원 마다")
            unit_amount_label.setStyleSheet("""
                QLabel {
                    font-size: 12pt;       /* 폰트 크기 설정 */
                    font-weight: bold;     /* 굵은 폰트 */
                    font-style: normal;    /* 기울임 없음 */
                }
            """)
            unit_amount_spin = CustomSpinBox()
            unit_amount_spin.setSuffix ("₩")
            unit_amount_spin.setValue(20000)
            unit_amount_spin.setSingleStep(1000)

            cost_label = QLabel("원 추가")
            cost_label.setStyleSheet("""
                QLabel {
                    font-size: 12pt;       /* 폰트 크기 설정 */
                    font-weight: bold;     /* 굵은 폰트 */
                    font-style: normal;    /* 기울임 없음 */
                }
            """)
            cost_spin = CustomSpinBox()
            cost_spin.setSuffix ("₩")
            cost_spin.setValue(8000 + 4000 * i)
            cost_spin.setSingleStep(1000)

            # QGroupBox 레이아웃 구성
            stage_group_box_layout.addWidget(min_amount_spin,0,0,1,2)
            stage_group_box_layout.addWidget(min_amount_label,1,1)
            stage_group_box_layout.addWidget(unit_amount_spin,2,0,1,2)
            stage_group_box_layout.addWidget(unit_amount_label,3,1)
            stage_group_box_layout.addWidget(cost_spin,4,0,1,2)
            stage_group_box_layout.addWidget(cost_label,5,1)
            stage_group_box.setLayout(stage_group_box_layout)
            
            # 전체 레이아웃에 QGroupBox 추가
            cmb_settings_layout.addWidget(stage_group_box)
            
            # 각 단계별 스핀박스를 저장하여 추후 참조 가능
            self.stage_widgets.append((min_amount_spin, unit_amount_spin, cost_spin))
        
        self.cmb_settings_group.setLayout(cmb_settings_layout)
        self.right_layout.addWidget(self.cmb_settings_group)
        main_layout.addLayout(self.right_layout,3)
    
        self.setLayout(main_layout)

        # DB 읽어와서 테이블에 표시
        self.load_db_to_table()
        self.set_column_widths()
        self.update_cmb_settings_from_db()
        self.load_level1_categories()

    def load_level1_categories(self):
        """1레벨 카테고리를 DB에서 로드하여 콤보박스에 추가"""
        query = "SELECT DISTINCT category1 FROM categories WHERE category1 IS NOT NULL"
        self.cursor.execute(query)
        rows = self.cursor.fetchall()
        
        for row in rows:
            self.level1_combo.addItem(row[0])

    def update_level2_combo(self):
        """1레벨 선택 시, 2레벨 콤보박스를 업데이트"""
        selected_level1 = self.level1_combo.currentText()
        self.level2_combo.clear()
        self.level2_combo.addItem("모두 보기")
        
        if selected_level1 == "모두 보기":
            return

        query = "SELECT DISTINCT category2 FROM categories WHERE category1 = ? AND category2 IS NOT NULL"
        self.cursor.execute(query, (selected_level1,))
        rows = self.cursor.fetchall()
        
        for row in rows:
            self.level2_combo.addItem(row[0])

    def update_level3_combo(self):
        """2레벨 선택 시, 3레벨 콤보박스를 업데이트"""
        selected_level1 = self.level1_combo.currentText()
        selected_level2 = self.level2_combo.currentText()
        self.level3_combo.clear()
        self.level3_combo.addItem("모두 보기")
        
        if selected_level2 == "모두 보기":
            return

        query = "SELECT DISTINCT category3 FROM categories WHERE category1 = ? AND category2 = ? AND category3 IS NOT NULL"
        self.cursor.execute(query, (selected_level1, selected_level2))
        rows = self.cursor.fetchall()
        
        for row in rows:
            self.level3_combo.addItem(row[0])

    def reset_comboboxes(self):
        """1레벨, 2레벨, 3레벨 콤보박스를 초기화하고 QTreeWidget을 전체 항목으로 필터링합니다."""
        # 각 레벨 콤보박스 초기화
        self.level1_combo.setCurrentIndex(0)
        self.level2_combo.clear()
        self.level3_combo.clear()

        # QTreeWidget 필터링 초기화 (모든 항목 표시)
        self.load_db_to_table()  # 이 메서드는 전체 데이터를 다시 로드하는 메서드입니다.

    def filter_category_tree(self):
        """선택된 1레벨, 2레벨, 3레벨 카테고리를 기준으로 트리뷰를 필터링"""
        selected_level1 = self.level1_combo.currentText()
        selected_level2 = self.level2_combo.currentText()
        selected_level3 = self.level3_combo.currentText()

        # 기본 쿼리와 조건을 설정
        query = '''SELECT id, category1, category2, category3, category4, crmobi_stage FROM categories WHERE 1=1'''
        args = []

        # 선택된 값에 따라 필터 추가
        if selected_level1 != "모두 보기":
            query += " AND category1 = ?"
            args.append(selected_level1)
        if selected_level2 != "모두 보기":
            query += " AND category2 = ?"
            args.append(selected_level2)
        if selected_level3 != "모두 보기":
            query += " AND category3 = ?"
            args.append(selected_level3)
        
        self.cursor.execute(query, args)
        rows = self.cursor.fetchall()
        
        # 트리뷰에 표시
        self.category_tree.clear()
        for row_data in rows:
            row_id, category1, category2, category3, category4, crmobi_stage = row_data
            formatted_id = str(row_id).zfill(4)
            top_item = QTreeWidgetItem([
                formatted_id,
                category1 or "", category2 or "",
                category3 or "", category4 or "",
                f"{crmobi_stage}" if crmobi_stage > 0 else "미적용"
            ])
            top_item.setCheckState(0, Qt.Unchecked)

            # 단계별 배경색 설정 QColor(R,G,B,A)
            if crmobi_stage == 1:
                color = QColor(152, 251, 152, 204)  # 옐로우그린
            elif crmobi_stage == 2:
                color = QColor(135, 206, 235, 204)  # 스카이블루
            elif crmobi_stage == 3:
                color = QColor(255, 192, 203, 204)  # 라이트핑크
            else:
                color = None

            # 행 전체에 배경색 적용
            if color:
                for col in range(6):  # 열의 개수에 따라 반복
                    top_item.setBackground(col, color)

            self.category_tree.addTopLevelItem(top_item)


    def update_cmb_settings_from_db(self):
        """DB의 crmobi_stages 테이블에서 값을 읽어와 각 단계별 설정 위젯에 반영합니다."""
        try:
            # CrMoBi 단계 설정을 crmobi_stages 테이블에서 가져옴
            self.cursor.execute("SELECT stage, threshold, increment_unit, extra_cost FROM crmobi_stages")
            stages = self.cursor.fetchall()

            # 각 단계별 설정 값을 위젯에 적용
            for stage in stages:
                stage_index = stage[0] - 1  # 단계가 1부터 시작하므로 인덱스를 맞추기 위해 -1
                min_amount, unit_amount, extra_cost = stage[1], stage[2], stage[3]
                
                # 위젯 리스트에서 해당 단계를 찾아서 설정
                self.stage_widgets[stage_index][0].setValue(min_amount)
                self.stage_widgets[stage_index][1].setValue(unit_amount)
                self.stage_widgets[stage_index][2].setValue(extra_cost)

            self.logger.debug("CrMoBi 단계 설정이 위젯에 반영되었습니다.")
        except Exception as e:
            self.logger.error(f"CrMoBi 단계 설정을 위젯에 반영하는 중 오류 발생: {e}", exc_info=True)

    def create_tables(self):
        """초기 DB를 생성하고 CrMoBi 단계 테이블도 추가합니다."""
        file_dialog = QFileDialog()
        excel_path, _ = file_dialog.getOpenFileName(self, "엑셀 파일 선택", "", "Excel Files (*.xlsx *.xls)")
            
        if excel_path:
            try:
                db_path = os.path.join("src", "initialDB.db")
                conn = sqlite3.connect(db_path)
                cursor = conn.cursor()
                
                # 테이블 생성
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS categories (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        category1 TEXT,
                        category2 TEXT,
                        category3 TEXT,
                        category4 TEXT,
                        crmobi_stage INTEGER DEFAULT 0
                    )
                ''')
                
                # 엑셀 파일에서 "스스 카테고리" 시트를 읽어옴
                sheet_name = '스스 카테고리'
                try:
                    # 시트의 첫 번째 열만 읽어옴
                    df = pd.read_excel(excel_path, sheet_name=sheet_name, header=None, usecols=[0])
                    df.columns = ["full_category"]  # 열 이름 지정
                    
                    # 카테고리 코드와 경로를 추출
                    for _, row in df.iterrows():
                        # 카테고리 코드 제거 및 텍스트 추출
                        full_text = row['full_category']
                        match = re.match(r'\[.*?\]\s*(.*)', full_text)
                        if match:
                            category_path = match.group(1)  # 대괄호 안의 카테고리 코드를 제외한 텍스트
                        
                            # 하이픈으로 카테고리 분할
                            category_parts = category_path.split('-')
                            category_levels = category_parts + [""] * (4 - len(category_parts))  # 4개로 맞추기 위해 빈 문자열 추가
                            
                            # 데이터베이스에 삽입
                            cursor.execute('''
                                INSERT INTO categories (category1, category2, category3, category4)
                                VALUES (?, ?, ?, ?)
                            ''', category_levels[:4])
                except Exception as sheet_error:
                    QMessageBox.warning(self, "시트 불러오기 오류", f"'{sheet_name}' 시트에서 데이터를 읽어오는 중 오류가 발생했습니다: {sheet_error}")

                # CrMoBi 단계 테이블 생성
                cursor.execute('''
                    CREATE TABLE IF NOT EXISTS crmobi_stages (
                        stage INTEGER PRIMARY KEY,
                        threshold INTEGER,
                        increment_unit INTEGER,
                        extra_cost INTEGER
                    )
                ''')
                
                # 초기 데이터 설정 (원하는 경우)
                cursor.execute('DELETE FROM crmobi_stages')
                conn.commit()

                for i in range(1, 4):
                    cursor.execute('''
                        INSERT INTO crmobi_stages (stage, threshold, increment_unit, extra_cost)
                        VALUES (?, ?, ?, ?)
                    ''', (i, 100000 * i, 20000, 5000 * i))
                
                conn.commit()
                conn.close()
                QMessageBox.information(self, "DB 생성", "DB가 성공적으로 생성되었습니다.")
            except Exception as e:
                QMessageBox.critical(self, "DB 생성 오류", f"DB 생성 중 오류가 발생했습니다: {e}")

    def load_db_to_table(self, search_text=None, cmb_stage=None):
        """DB에서 데이터를 읽어와 테이블에 표시하고 배경색을 설정합니다."""
        self.category_tree.clear()
        
        # 기본 쿼리와 조건을 설정
        query = '''SELECT id, category1, category2, category3, category4, crmobi_stage FROM categories WHERE 1=1'''
        args = []
        
        # 검색어가 있을 경우 WHERE 조건 추가
        if search_text:
            query += ''' AND (category1 LIKE ? OR category2 LIKE ? OR category3 LIKE ? OR category4 LIKE ?)'''
            args.extend([f"%{search_text}%"] * 4)
        
        # CMB 단계 필터링 조건 추가
        if cmb_stage:
            query += " AND crmobi_stage = ?"
            args.append(cmb_stage)
        
        self.cursor.execute(query, args)
        rows = self.cursor.fetchall()

        # id 기준 오름차순 정렬을 위해 정렬
        rows = sorted(rows, key=lambda x: int(x[0]))  # x[0]는 id 열

        for row_data in rows:
            row_id, category1, category2, category3, category4, crmobi_stage = row_data
            formatted_id = str(row_id).zfill(4)
            top_item = QTreeWidgetItem([formatted_id, category1 or "", category2 or "", category3 or "", category4 or "", f"{crmobi_stage}" if crmobi_stage > 0 else "미적용"])
            top_item.setCheckState(0, Qt.Unchecked)
            
            # id 값을 정수로 설정하여 정렬 시 정수 기준으로 처리되도록 함
            top_item.setData(0, Qt.UserRole, int(row_id))

            # 단계별 배경색 설정 QColor(R,G,B,A)
            if crmobi_stage == 1:
                color = QColor(152, 251, 152, 204)  # 옐로우그린
            elif crmobi_stage == 2:
                color = QColor(135, 206, 235, 204)  # 스카이블루
            elif crmobi_stage == 3:
                color = QColor(255, 192, 203, 204)  # 라이트핑크
            else:
                color = None

            # 행 전체에 배경색 적용
            if color:
                for col in range(6):  # 열의 개수에 따라 반복
                    top_item.setBackground(col, color)
                    
            self.category_tree.addTopLevelItem(top_item)

        # 초기 정렬 기준을 id 열로 설정하고 오름차순 정렬
        self.category_tree.setSortingEnabled(True)
        self.category_tree.sortByColumn(0, Qt.AscendingOrder)  # ID 열을 기준으로 오름차순 정렬

    def set_column_widths(self):
        """ID 열 너비를 일정하게 설정"""
        current_id_width = self.category_tree.columnWidth(0)
        self.category_tree.setColumnWidth(0, int(current_id_width / 1.5))  # ID 열을 초기 설정 크기로 유지


    def sort_by_column(self, index):
        """클릭된 열을 기준으로 오름차순/내림차순으로 정렬"""
        # 정렬 역할을 UserRole로 설정하여 ID 필드가 정수로 정렬되도록 설정
        self.category_tree.setSortingEnabled(False)  # 정렬을 일시적으로 비활성화
        self.category_tree.sortItems(index, self.sort_order)
        self.category_tree.setSortingEnabled(True)  # 정렬을 다시 활성화

        # 정렬 순서를 토글
        self.sort_order = Qt.DescendingOrder if self.sort_order == Qt.AscendingOrder else Qt.AscendingOrder

    def apply_crmobi_stage(self, stage):
        """선택된 카테고리에 CrMoBi 단계를 적용하고 DB에 저장."""
        for i in range(self.category_tree.topLevelItemCount()):
            item = self.category_tree.topLevelItem(i)
            if item.checkState(0) == Qt.Checked:
                category_values = [item.text(j) for j in range(1, 5)]  # ID 열 제외
                # DB 업데이트
                self.cursor.execute('''UPDATE categories 
                                    SET crmobi_stage = ? 
                                    WHERE category1 = ? AND category2 = ? AND category3 = ? AND category4 = ?''',
                                    [stage] + category_values)

        self.conn.commit()  # 변경사항 저장
        self.load_db_to_table()  # 트리 새로고침
        
    def remove_cmb_stage(self):
        """선택된 카테고리의 CMB 단계를 해제하고 DB에 반영."""
        for i in range(self.category_tree.topLevelItemCount()):
            item = self.category_tree.topLevelItem(i)
            if item.checkState(0) == Qt.Checked:
                category_id = int(item.text(0))  # ID 열에서 값 가져오기
                # DB에서 CMB 단계를 해제
                self.cursor.execute("UPDATE categories SET crmobi_stage = 0 WHERE id = ?", (category_id,))

        self.conn.commit()
        self.load_db_to_table()  # 트리 새로고침

    def toggle_cmb_settings(self, checked):
        """CMB 단계 설정 영역 표시/숨기기, 공간을 완전히 제거 또는 복원합니다."""
        sender = self.sender()

        if checked:
            # 공간에 cmb_settings_group 추가
            self.right_layout.addWidget(self.cmb_settings_group)
            self.cmb_settings_group.show()
            sender.setText("CMB 단계 설정 ▼")
        else:
            # cmb_settings_group 숨기기 및 제거
            self.cmb_settings_group.hide()
            self.right_layout.removeWidget(self.cmb_settings_group)
            sender.setText("CMB 단계 설정 ▶")

        # 레이아웃을 다시 갱신하여 공간을 완전히 반영
        self.layout().update()
    def toggle_select_all_filtered_items(self):
        """버튼의 텍스트에 따라 전체 선택 또는 전체 해제를 수행합니다."""
        if self.select_toggle_button.text() == "전체 선택":
            # 전체 체크
            for i in range(self.category_tree.topLevelItemCount()):
                item = self.category_tree.topLevelItem(i)
                item.setCheckState(0, Qt.Checked)
            # 버튼 텍스트를 "전체 해제"로 변경
            self.select_toggle_button.setText("전체 해제")
        else:
            # 전체 체크 해제
            for i in range(self.category_tree.topLevelItemCount()):
                item = self.category_tree.topLevelItem(i)
                item.setCheckState(0, Qt.Unchecked)
            # 버튼 텍스트를 "전체 선택"으로 변경
            self.select_toggle_button.setText("전체 선택")

    def save_cmb_stage_to_db(self):
        """사용자가 설정한 CMB 단계를 crmobi_stage 테이블에 저장합니다."""
        try:
            # 각 CMB 단계의 설정을 불러옵니다
            for i, (min_amount_spin, unit_amount_spin, cost_spin) in enumerate(self.stage_widgets, start=1):
                stage = i
                threshold = min_amount_spin.value()
                increment_unit = unit_amount_spin.value()
                extra_cost = cost_spin.value()
                
                # 기존 데이터가 있는지 확인
                self.cursor.execute("SELECT COUNT(1) FROM crmobi_stages WHERE stage = ?", (stage,))
                exists = self.cursor.fetchone()[0]
                
                # 데이터를 업데이트 또는 삽입
                if exists:
                    self.cursor.execute('''
                        UPDATE crmobi_stages 
                        SET threshold = ?, increment_unit = ?, extra_cost = ? 
                        WHERE stage = ?
                    ''', (threshold, increment_unit, extra_cost, stage))
                else:
                    self.cursor.execute('''
                        INSERT INTO crmobi_stages (stage, threshold, increment_unit, extra_cost)
                        VALUES (?, ?, ?, ?)
                    ''', (stage, threshold, increment_unit, extra_cost))
            
            # 변경사항 저장
            self.conn.commit()
            QMessageBox.information(self, "저장 성공", "CMB 단계 설정이 성공적으로 저장되었습니다.")
        
        except Exception as e:
            QMessageBox.critical(self, "저장 오류", f"저장 중 오류가 발생했습니다: {e}")
            self.logger.error(f"CMB 단계 저장 중 오류: {e}", exc_info=True)

    def reset_db(self):
        """사용자 DB를 삭제하고 초기 DB를 로드합니다."""
        if os.path.exists(self.user_db_path):
            os.remove(self.user_db_path)
            shutil.copyfile(self.initial_db_path, self.user_db_path)
        
        QMessageBox.information(self, "DB 초기화", "사용자 DB가 삭제되었습니다. 초기 DB를 로드합니다.")
        self.load_db_to_table()

    def save_user_db(self):
        """사용자가 설정한 내용을 저장하여 사용자 DB로 생성합니다."""
        # 테이블 생성
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS categories (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                category1 TEXT,
                category2 TEXT,
                category3 TEXT,
                category4 TEXT
            )
        ''')
        
        # 기존 데이터를 모두 삭제
        self.cursor.execute("DELETE FROM categories")
        
        # 테이블 데이터 삽입
        for row_idx in range(self.category_table.rowCount()):
            row_data = [
                self.category_table.item(row_idx, col_idx).text() if self.category_table.item(row_idx, col_idx) else ""
                for col_idx in range(4)
            ]
            self.cursor.execute("INSERT INTO categories (category1, category2, category3, category4) VALUES (?, ?, ?, ?)", row_data)
        
        QMessageBox.information(self, "DB 저장", "사용자 DB가 저장되었습니다.")

    def toggle_cmb_view(self):
        """CMB 보기 버튼을 클릭할 때마다 단계별로 토글하여 필터링합니다."""
        current_text = self.cmb_view_btn.text()
        
        if current_text == "모두 보기":
            self.cmb_view_btn.setText("1단계 보기")
            self.load_db_to_table(cmb_stage=1)
        elif current_text == "1단계 보기":
            self.cmb_view_btn.setText("2단계 보기")
            self.load_db_to_table(cmb_stage=2)
        elif current_text == "2단계 보기":
            self.cmb_view_btn.setText("3단계 보기")
            self.load_db_to_table(cmb_stage=3)
        else:
            self.cmb_view_btn.setText("모두 보기")
            self.load_db_to_table()

    def search_category(self):
        """카테고리 검색 기능."""
        search_text = self.search_input.text().strip()
        if search_text:
            # 검색어가 있는 경우 필터링하여 로드
            query = '''
                SELECT id, category1, category2, category3, category4, crmobi_stage 
                FROM categories 
                WHERE category1 LIKE ? OR category2 LIKE ? OR category3 LIKE ? OR category4 LIKE ?
            '''
            args = [f"%{search_text}%"] * 4
            self.cursor.execute(query, args)
        else:
            # 검색어가 없는 경우 전체 로드
            query = '''
                SELECT id, category1, category2, category3, category4, crmobi_stage 
                FROM categories
            '''
            self.cursor.execute(query)
        
        # 검색 결과를 트리에 표시
        self.category_tree.clear()
        rows = self.cursor.fetchall()
        
        for row_data in rows:
            # top_item = QTreeWidgetItem([str(data) if data else "" for data in row_data[:4]])
            row_id, category1, category2, category3, category4, crmobi_stage = row_data
            formatted_id = str(row_id).zfill(4)
            top_item = QTreeWidgetItem([formatted_id, category1 or "", category2 or "", category3 or "", category4 or "", f"{crmobi_stage}" if crmobi_stage > 0 else "미적용"])

            crmobi_stage = row_data[5]
            top_item.setCheckState(0, Qt.Unchecked)
            top_item.setText(5, f"{crmobi_stage}" if crmobi_stage > 0 else "미적용")

            # 단계별 배경색 설정 QColor(R,G,B,A)
            if crmobi_stage == 1:
                color = QColor(152, 251, 152, 204)  # 옐로우그린
            elif crmobi_stage == 2:
                color = QColor(135, 206, 235, 204)  # 스카이블루
            elif crmobi_stage == 3:
                color = QColor(255, 192, 203, 204)  # 라이트핑크
            else:
                color = None

            # 행 전체에 배경색 적용
            if color:
                for col in range(6):  # 열의 개수에 따라 반복
                    top_item.setBackground(col, color)
            
            self.category_tree.addTopLevelItem(top_item)
        
    def get_crmobi_stage(self, category):
        """
        주어진 카테고리에 해당하는 CMB 단계가 설정되어 있는지 확인하고,
        설정된 경우 해당 단계의 범위를 반환합니다.

        Parameters:
            category (str): 카테고리 이름 (예: '가구/인테리어')

        Returns:
            tuple: (min_amount, unit_amount, extra_cost) 값이 있는 경우
            None: 설정된 CMB 단계가 없는 경우
        """
        try:
            # DB에서 카테고리에 대한 CMB 단계 정보를 가져옴
            query = '''
                SELECT crmobi_stage FROM categories 
                WHERE category1 = ? OR category2 = ? OR category3 = ? OR category4 = ?
            '''

            self.logger.debug(f"category : {category}")
            args = [category] * 4
            self.cursor.execute(query, args)
            result = self.cursor.fetchone()

            if result and result[0] > 0:  # CMB 단계가 설정되어 있을 때
                crmobi_stage = result[0]
                
                # 설정된 CMB 단계에 해당하는 범위 가져오기
                stage_query = '''
                    SELECT threshold, increment_unit, extra_cost 
                    FROM crmobi_stages 
                    WHERE stage = ?
                '''
                self.cursor.execute(stage_query, (crmobi_stage,))
                stage_result = self.cursor.fetchone()
                self.logger.debug(f"stage_result : {stage_result}")

                if stage_result:
                    min_amount, unit_amount, extra_cost = stage_result
                    return (min_amount, unit_amount, extra_cost)
            
            # CMB 단계가 설정되지 않은 경우
            return None

        except Exception as e:
            QMessageBox.critical(self, "DB 오류", f"DB 조회 중 오류가 발생했습니다: {e}")
            return None

    def closeEvent(self, event):
        """QDialog 종료 시 DB 연결 해제"""
        self.conn.close()
        event.accept()

    def focusInEvent(self, event):
        """ 다이얼로그에 포커스가 들어올 때 검색 필드에 포커스를 강제 설정 """
        self.search_input.setFocus()
        super().focusInEvent(event)






class CustomSpinBox(QSpinBox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # 폰트 설정
        font = QFont()
        font.setPointSize(10)  # 폰트 크기 설정
        font.setBold(True)     # 폰트 굵게 설정
        self.setFont(font)
        
        # 스핀박스 설정
        self.setRange(0, 1000000)
        self.setSingleStep(10000)

    def textFromValue(self, value):
        """숫자를 3자리마다 콤마 추가된 형식으로 표시"""
        return f"{value:,}"
