import customtkinter as ctk
from tkinter import filedialog
import os
from datetime import datetime

ctk.set_appearance_mode("System")
ctk.set_default_color_theme("blue")

IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}


class BatchRenameApp(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("批量圖片改名工具")
        self.geometry("700x580")
        self.resizable(False, False)
        self.folder_path = ""
        self.image_files = []
        self._build_ui()

    def _build_ui(self):
        # --- 資料夾選擇區 ---
        folder_frame = ctk.CTkFrame(self)
        folder_frame.pack(fill="x", padx=20, pady=(20, 10))

        ctk.CTkLabel(folder_frame, text="資料夾：",
                     font=("微軟正黑體", 14)).pack(side="left", padx=10)

        self.folder_label = ctk.CTkLabel(folder_frame, text="尚未選擇資料夾",
                                         text_color="gray",
                                         font=("微軟正黑體", 13),
                                         anchor="w")
        self.folder_label.pack(side="left", fill="x", expand=True, padx=5)

        ctk.CTkButton(folder_frame, text="選擇資料夾", width=120,
                      command=self._select_folder).pack(side="right", padx=10, pady=10)

        # --- 前綴輸入區 ---
        prefix_frame = ctk.CTkFrame(self)
        prefix_frame.pack(fill="x", padx=20, pady=10)

        ctk.CTkLabel(prefix_frame, text="前綴文字：",
                     font=("微軟正黑體", 14)).pack(side="left", padx=10)

        self.prefix_entry = ctk.CTkEntry(prefix_frame,
                                         placeholder_text="例如：側視圖片",
                                         height=35,
                                         font=("微軟正黑體", 13))
        self.prefix_entry.pack(side="left", fill="x", expand=True, padx=5, pady=10)

        ctk.CTkButton(prefix_frame, text="預覽", width=80,
                      command=self._preview).pack(side="right", padx=10)

        # --- 格式說明 ---
        today = datetime.today().strftime("%Y.%m.%d")
        hint = f"命名格式：前綴文字_{today}_01.jpg"
        ctk.CTkLabel(self, text=hint,
                     text_color="gray",
                     font=("微軟正黑體", 12)).pack(anchor="w", padx=22, pady=(0, 5))

        # --- 預覽區 ---
        ctk.CTkLabel(self, text="更名預覽",
                     font=("微軟正黑體", 14)).pack(anchor="w", padx=22, pady=(5, 2))

        self.preview_box = ctk.CTkTextbox(self, height=300,
                                          font=("Consolas", 12),
                                          state="disabled")
        self.preview_box.pack(fill="both", expand=True, padx=20, pady=(0, 10))

        # --- 底部執行區 ---
        bottom_frame = ctk.CTkFrame(self, fg_color="transparent")
        bottom_frame.pack(fill="x", padx=20, pady=(0, 20))

        self.status_label = ctk.CTkLabel(bottom_frame, text="",
                                         font=("微軟正黑體", 13))
        self.status_label.pack(side="left")

        self.execute_btn = ctk.CTkButton(bottom_frame,
                                         text="執行改名",
                                         width=120,
                                         fg_color="#2ECC71",
                                         hover_color="#27AE60",
                                         font=("微軟正黑體", 14, "bold"),
                                         state="disabled",
                                         command=self._execute_rename)
        self.execute_btn.pack(side="right")

        # 初始預覽提示
        self._write_preview("（選擇資料夾並輸入前綴後，點擊「預覽」查看改名結果）")

    # ── 內部方法 ──────────────────────────────────────────

    def _select_folder(self):
        path = filedialog.askdirectory(title="選擇圖片資料夾")
        if not path:
            return
        self.folder_path = path
        self.folder_label.configure(text=path, text_color="white")
        self._scan_folder()

    def _scan_folder(self):
        all_files = sorted(os.listdir(self.folder_path))
        self.image_files = [
            f for f in all_files
            if os.path.splitext(f)[1].lower() in IMAGE_EXTENSIONS
        ]
        count = len(self.image_files)
        if count == 0:
            self._set_status("此資料夾內沒有圖片", "#E74C3C")
        else:
            self._set_status(f"找到 {count} 張圖片，請輸入前綴後點擊「預覽」", "gray")
        self.execute_btn.configure(state="disabled")
        self._write_preview("（請輸入前綴後點擊「預覽」）")

    def _build_new_names(self):
        """回傳 (pairs, error_msg)。pairs 為 [(舊名, 新名), ...]"""
        prefix = self.prefix_entry.get().strip()
        if not prefix:
            return None, "請輸入前綴文字"
        date_str = datetime.today().strftime("%Y.%m.%d")
        pairs = []
        for i, filename in enumerate(self.image_files, start=1):
            ext = os.path.splitext(filename)[1].lower()
            new_name = f"{prefix}_{date_str}_{i:02d}{ext}"
            pairs.append((filename, new_name))
        return pairs, None

    def _preview(self):
        if not self.folder_path:
            self._set_status("請先選擇資料夾", "#E74C3C")
            return
        if not self.image_files:
            self._set_status("資料夾內沒有圖片", "#E74C3C")
            return

        pairs, error = self._build_new_names()
        if error:
            self._set_status(error, "#E74C3C")
            return

        lines = [f"{old}\n    → {new}\n" for old, new in pairs]
        self._write_preview("".join(lines))
        self.execute_btn.configure(state="normal")
        self._set_status(f"共 {len(pairs)} 張圖片待改名，確認無誤後點擊「執行改名」", "gray")

    def _execute_rename(self):
        pairs, error = self._build_new_names()
        if error:
            self._set_status(error, "#E74C3C")
            return

        success, fail = 0, 0
        for old, new in pairs:
            try:
                os.rename(
                    os.path.join(self.folder_path, old),
                    os.path.join(self.folder_path, new)
                )
                success += 1
            except Exception:
                fail += 1

        if fail == 0:
            self._set_status(f"完成！成功改名 {success} 張圖片", "#2ECC71")
            self.execute_btn.configure(state="disabled")
            self._scan_folder()
        else:
            self._set_status(f"完成 {success} 張，失敗 {fail} 張（請確認檔案未被佔用）", "#E67E22")

    # ── 工具方法 ──────────────────────────────────────────

    def _write_preview(self, text: str):
        self.preview_box.configure(state="normal")
        self.preview_box.delete("0.0", "end")
        self.preview_box.insert("0.0", text)
        self.preview_box.configure(state="disabled")

    def _set_status(self, msg: str, color: str):
        self.status_label.configure(text=msg, text_color=color)


if __name__ == "__main__":
    app = BatchRenameApp()
    app.mainloop()
