from PySide6.QtWidgets import (QDialog, QFileDialog, QVBoxLayout, QHBoxLayout, QGridLayout, QTreeWidget, QTreeWidgetItem, QLabel, QLineEdit, QPushButton,
                               QSpinBox, QGroupBox, QFileDialog, QMessageBox, QCheckBox)
from PySide6.QtCore import Qt
from PySide6.QtGui import QFont
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()        
        right_layout = QVBoxLayout()
        

        # 카테고리 검색 및 단계 설정 버튼
        search_layout = QHBoxLayout()
        search_layout.addWidget(QLabel("카테고리 검색:"))
        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)
        search_layout.addWidget(self.search_btn)
        self.cmb_view_btn = QPushButton("모두 보기")
        self.cmb_view_btn.clicked.connect(self.toggle_cmb_view)
        search_layout.addWidget(self.cmb_view_btn)

        left_layout.addLayout(search_layout, 1)
        
        # 카테고리 목록 테이블
        self.category_tree = QTreeWidget()
        self.category_tree.setHeaderLabels(["Level1", "Level2", "Level3", "Level4", "CMB 단계"])
        self.category_tree.setColumnCount(5)
        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단계 적용")
        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))
        mid_layout.addWidget(apply_1_btn)
        mid_layout.addWidget(apply_2_btn)
        mid_layout.addWidget(apply_3_btn)

        # 닫기 버튼
        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()
        
        # 각 단계별 설정
        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)
            stage_group_box_layout.addWidget(min_amount_label,0,1)
            stage_group_box_layout.addWidget(unit_amount_spin,1,0)
            stage_group_box_layout.addWidget(unit_amount_label,1,1)
            stage_group_box_layout.addWidget(cost_spin,2,0)
            stage_group_box_layout.addWidget(cost_label,2,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)
        right_layout.addWidget(self.cmb_settings_group)
        main_layout.addLayout(right_layout,2)
    
        self.setLayout(main_layout)

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

    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 (
                        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
                    )
                ''')
                
                # 초기 데이터 설정 (원하는 경우)
                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 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()
        
        for row_data in rows:
            top_item = QTreeWidgetItem([str(data) if data else "" for data in row_data[:4]])
            crmobi_stage = row_data[4]
            top_item.setCheckState(0, Qt.Unchecked)
            top_item.setText(4, f"{crmobi_stage}" if crmobi_stage > 0 else "미적용")

            # 단계별 배경색 설정
            if crmobi_stage == 1:
                top_item.setBackground(4, Qt.yellow)
            elif crmobi_stage == 2:
                top_item.setBackground(4, Qt.green)
            elif crmobi_stage == 3:
                top_item.setBackground(4, Qt.red)
                
            self.category_tree.addTopLevelItem(top_item)

    def sort_by_column(self, index):
        """클릭된 열을 기준으로 오름차순/내림차순으로 정렬"""
        self.category_tree.sortByColumn(index, self.sort_order)
        
        # 정렬 순서를 토글
        self.sort_order = Qt.DescendingOrder if self.sort_order == Qt.AscendingOrder else Qt.AscendingOrder

    def apply_crmobi_stage(self, stage):
        """선택된 카테고리에 CrMoBi 단계를 적용합니다."""
        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(4)]
                
                # DB 업데이트
                self.cursor.execute('''UPDATE categories 
                                       SET crmobi_stage = ? 
                                       WHERE category1 = ? AND category2 = ? AND category3 = ? AND category4 = ?''',
                                    [stage] + category_values)
                
                # 트리뷰 업데이트
                item.setText(4, str(stage))
                if stage == 1:
                    item.setBackground(4, Qt.yellow)
                elif stage == 2:
                    item.setBackground(4, Qt.green)
                elif stage == 3:
                    item.setBackground(4, Qt.red)

        self.conn.commit()  # 변경사항 저장
        self.load_db_to_table()  # 트리 새로고침
    
    def toggle_cmb_settings(self, checked):
        """CMB 단계 설정 영역 표시/숨기기"""
        self.cmb_settings_group.setVisible(checked)

        sender = self.sender()
        if checked:
            sender.setText("CMB 단계 설정 ▼")
        else:
            sender.setText("CMB 단계 설정 ▶")
    
    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 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 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]])
            crmobi_stage = row_data[4]
            top_item.setCheckState(0, Qt.Unchecked)
            top_item.setText(4, f"{crmobi_stage}" if crmobi_stage > 0 else "미적용")

            # 단계별 배경색 설정
            if crmobi_stage == 1:
                top_item.setBackground(4, Qt.yellow)
            elif crmobi_stage == 2:
                top_item.setBackground(4, Qt.green)
            elif crmobi_stage == 3:
                top_item.setBackground(4, Qt.red)
            
            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(12)  # 폰트 크기 설정
        font.setBold(True)     # 폰트 굵게 설정
        self.setFont(font)
        
        # 스핀박스 설정
        self.setRange(0, 1000000)
        self.setSingleStep(10000)

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