import sys, os, re, shutil
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QPushButton, QLabel, QLineEdit,
    QProgressBar, QFileDialog, QVBoxLayout, QWidget, QHBoxLayout, QComboBox
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal

# 백그라운드에서 파일 복사를 수행하는 QThread 클래스
class FileCopyThread(QThread):
    progress = pyqtSignal(int)           # 진행률(%) 업데이트 신호
    copied_count_signal = pyqtSignal(int)  # 복사된 파일 수 업데이트 신호

    def __init__(self, source_dir, target_dir, parent=None):
        super().__init__(parent)
        self.source_dir = source_dir
        self.target_dir = target_dir
        self.is_running = True

    def run(self):
        files = [f for f in os.listdir(self.source_dir) if f.lower().endswith('.mov')]
        total = len(files)
        copied_count = 0

        for i, file_name in enumerate(files):
            if not self.is_running:
                break

            source_file = os.path.join(self.source_dir, file_name)
            match = re.search(r'(TK\d+)', file_name, re.IGNORECASE)
            if match:
                folder_name = match.group(1)
            else:
                folder_name = "Others"

            dest_folder = os.path.join(self.target_dir, folder_name)
            if not os.path.exists(dest_folder):
                os.makedirs(dest_folder)

            dest_file = os.path.join(dest_folder, file_name)
            try:
                shutil.copy2(source_file, dest_file)
                copied_count += 1
            except Exception as e:
                print(f"파일 복사 에러: {source_file} -> {dest_file}\n{e}")

            progress_percent = int((i + 1) / total * 100) if total else 0
            self.progress.emit(progress_percent)
            self.copied_count_signal.emit(copied_count)

    def stop(self):
        self.is_running = False
        self.wait()


class MainWindow(QMainWindow):
    PROJECT_PATHS = {
        "BB": "/System/Volumes/Data/usadata3/Bento_Project",
        "KOTH": "/System/Volumes/Data/usadata2/Disney/KOTH",
        "Big_Mouth": "/System/Volumes/Data/usadata2/Titmouse/Big_Mouth",
        "TGN": "/System/Volumes/Data/usadata3/Bento_Project2/Great_North",
        "Test": "/System/Volumes/Data/usadata3/Test",
        "Yeson_Test": "/System/Volumes/Data/usadata3/Yeson_Test",
        "Yeson_Test_4K": "/System/Volumes/Data/usadata3/Yeson_Test_4K"
    }

    def __init__(self):
        super().__init__()
        self.setWindowTitle("MOV 파일 복사 앱")
        self.resize(500, 400)

        # 작품 선택 UI
        self.project_label = QLabel("작품 선택:")
        self.project_combo = QComboBox()
        self.project_combo.addItems(self.PROJECT_PATHS.keys())
        self.project_combo.currentTextChanged.connect(self.update_seasons)

        # Season 선택 UI
        self.season_label = QLabel("Season 선택:")
        self.season_combo = QComboBox()
        self.season_combo.currentTextChanged.connect(self.update_jobs)

        # Jobs 선택 UI
        self.jobs_label = QLabel("Jobs 선택:")
        self.jobs_combo = QComboBox()
        self.jobs_combo.currentTextChanged.connect(self.update_scenes)

        # Scene 선택 UI
        self.scene_label = QLabel("Scene 선택:")
        self.scene_combo = QComboBox()

        # 대상 폴더 선택 UI
        self.target_label = QLabel("대상 폴더:")
        self.target_edit = QLineEdit()
        self.target_button = QPushButton("찾아보기")
        self.target_button.clicked.connect(self.select_target)

        # 복사 시작 및 초기화 버튼
        self.start_button = QPushButton("복사 시작")
        self.start_button.clicked.connect(self.start_copy)
        self.reset_button = QPushButton("초기화")
        self.reset_button.clicked.connect(self.reset)

        # 진행률 표시 및 복사된 파일 수 표시
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        self.copied_count_label = QLabel("복사된 파일 수: 0")

        # 레이아웃 구성
        layout = QVBoxLayout()

        project_layout = QHBoxLayout()
        project_layout.addWidget(self.project_label)
        project_layout.addWidget(self.project_combo)
        layout.addLayout(project_layout)

        season_layout = QHBoxLayout()
        season_layout.addWidget(self.season_label)
        season_layout.addWidget(self.season_combo)
        layout.addLayout(season_layout)

        jobs_layout = QHBoxLayout()
        jobs_layout.addWidget(self.jobs_label)
        jobs_layout.addWidget(self.jobs_combo)
        layout.addLayout(jobs_layout)

        scene_layout = QHBoxLayout()
        scene_layout.addWidget(self.scene_label)
        scene_layout.addWidget(self.scene_combo)
        layout.addLayout(scene_layout)

        target_layout = QHBoxLayout()
        target_layout.addWidget(self.target_label)
        target_layout.addWidget(self.target_edit)
        target_layout.addWidget(self.target_button)
        layout.addLayout(target_layout)

        layout.addWidget(self.start_button)
        layout.addWidget(self.reset_button)
        layout.addWidget(self.progress_bar)
        layout.addWidget(self.copied_count_label)

        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        self.copy_thread = None
        self.update_seasons()  # 초기 Season 목록 업데이트

    def update_seasons(self):
        self.season_combo.clear()
        project = self.project_combo.currentText()
        project_path = self.PROJECT_PATHS.get(project, "")
        if os.path.exists(project_path):
            folders = [f for f in os.listdir(project_path) if os.path.isdir(os.path.join(project_path, f))]
            self.season_combo.addItems(folders)
        self.update_jobs()

    def update_jobs(self):
        self.jobs_combo.clear()
        project = self.project_combo.currentText()
        season = self.season_combo.currentText()
        project_path = self.PROJECT_PATHS.get(project, "")
        season_path = os.path.join(project_path, season)
        if os.path.exists(season_path):
            folders = [f for f in os.listdir(season_path) if os.path.isdir(os.path.join(season_path, f))]
            self.jobs_combo.addItems(folders)
        self.update_scenes()

    def update_scenes(self):
        self.scene_combo.clear()
        project = self.project_combo.currentText()
        season = self.season_combo.currentText()
        job = self.jobs_combo.currentText()
        project_path = self.PROJECT_PATHS.get(project, "")
        job_path = os.path.join(project_path, season, job)
        if os.path.exists(job_path):
            folders = [f for f in os.listdir(job_path) if os.path.isdir(os.path.join(job_path, f))]
            self.scene_combo.addItems(folders)

    def select_target(self):
        folder = QFileDialog.getExistingDirectory(self, "대상 폴더 선택")
        if folder:
            self.target_edit.setText(folder)

    def start_copy(self):
        project = self.project_combo.currentText()
        season = self.season_combo.currentText()
        job = self.jobs_combo.currentText()
        scene = self.scene_combo.currentText()
        source_dir = os.path.join(self.PROJECT_PATHS.get(project, ""), season, job, scene)
        target_dir = self.target_edit.text().strip()

        if not os.path.exists(source_dir) or not target_dir:
            return  # 경로가 유효하지 않으면 동작하지 않음

        self.start_button.setEnabled(False)
        self.copy_thread = FileCopyThread(source_dir, target_dir)
        self.copy_thread.progress.connect(self.progress_bar.setValue)
        self.copy_thread.copied_count_signal.connect(self.update_copied_count)
        self.copy_thread.finished.connect(self.copy_finished)
        self.copy_thread.start()

    def update_copied_count(self, count):
        self.copied_count_label.setText(f"복사된 파일 수: {count}")

    def copy_finished(self):
        self.start_button.setEnabled(True)

    def reset(self):
        if self.copy_thread is not None:
            self.copy_thread.stop()
            self.copy_thread = None
        self.project_combo.setCurrentIndex(0)
        self.update_seasons()
        self.target_edit.clear()
        self.progress_bar.setValue(0)
        self.copied_count_label.setText("복사된 파일 수: 0")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())