#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量文件重命名工具
支持添加文件，按顺序重命名
"""

import os
import sys
import tkinter as tk
from tkinter import Label, Button, Entry, messagebox, Frame, Scrollbar, Listbox, VERTICAL, HORIZONTAL, END, filedialog

class BatchRenameApp:
    def __init__(self, root):
        self.root = root
        self.root.title("批量文件重命名工具")
        self.root.geometry("750x800")
        self.root.resizable(True, True)
        
        # 初始化变量
        self.file_list = []
        self.new_prefix = "renamed"
        self.start_number = 1
        self.number_digits = 3
        
        # 创建界面
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = Frame(self.root, padx=20, pady=20)
        main_frame.pack(fill="both", expand=True)
        
        # 提示区域
        drop_frame = Frame(main_frame, pady=10, bg="#E3F2FD", relief="solid", bd=2)
        drop_frame.pack(fill="x")
        
        self.drop_label = Label(drop_frame, text='📁 点击下方"添加文件"按钮选择文件', 
                                font=("SimHei", 14, "bold"), bg="#E3F2FD", fg="#1976D2",
                                height=2)
        self.drop_label.pack(fill="x", expand=True)
        
        # 按钮区域
        btn_frame = Frame(main_frame, pady=10)
        btn_frame.pack(fill="x")
        
        Button(btn_frame, text="添加文件", command=self.add_files, font=("SimHei", 10), width=12).pack(side="left", padx=5)
        Button(btn_frame, text="清空列表", command=self.clear_list, font=("SimHei", 10), width=12).pack(side="left", padx=5)
        Button(btn_frame, text="上移", command=self.move_up, font=("SimHei", 10), width=8).pack(side="left", padx=5)
        Button(btn_frame, text="下移", command=self.move_down, font=("SimHei", 10), width=8).pack(side="left", padx=5)
        Button(btn_frame, text="移除选中", command=self.remove_selected, font=("SimHei", 10), width=10).pack(side="left", padx=5)
        
        # 文件列表
        list_frame = Frame(main_frame, pady=10)
        list_frame.pack(fill="both", expand=True)
        
        Label(list_frame, text="文件列表 (按顺序重命名):", font=("SimHei", 10, "bold")).pack(anchor="w")
        
        # 列表框容器
        list_container = Frame(list_frame)
        list_container.pack(fill="both", expand=True, pady=5)
        
        # 文件列表
        self.file_listbox = Listbox(list_container, width=80, height=12, selectmode="single")
        self.file_listbox.pack(side="left", fill="both", expand=True)
        
        # 垂直滚动条
        vscrollbar = Scrollbar(list_container, orient=VERTICAL, command=self.file_listbox.yview)
        vscrollbar.pack(side="right", fill="y")
        self.file_listbox.config(yscrollcommand=vscrollbar.set)
        
        # 水平滚动条
        hscrollbar = Scrollbar(list_container, orient=HORIZONTAL, command=self.file_listbox.xview)
        hscrollbar.pack(side="bottom", fill="x")
        self.file_listbox.config(xscrollcommand=hscrollbar.set)
        
        # 重命名设置
        settings_frame = Frame(main_frame, pady=10)
        settings_frame.pack(fill="x")
        
        Label(settings_frame, text="重命名设置:", font=("SimHei", 10, "bold")).pack(anchor="w")
        
        # 前缀
        prefix_frame = Frame(settings_frame)
        prefix_frame.pack(fill="x", pady=5)
        
        Label(prefix_frame, text="新名称前缀:", width=15).pack(side="left", padx=5)
        self.prefix_entry = Entry(prefix_frame, width=40)
        self.prefix_entry.insert(0, self.new_prefix)
        self.prefix_entry.pack(side="left", padx=5)
        
        # 起始编号
        start_frame = Frame(settings_frame)
        start_frame.pack(fill="x", pady=5)
        
        Label(start_frame, text="起始编号:", width=15).pack(side="left", padx=5)
        self.start_entry = Entry(start_frame, width=10)
        self.start_entry.insert(0, str(self.start_number))
        self.start_entry.pack(side="left", padx=5)
        
        # 编号位数
        digits_frame = Frame(settings_frame)
        digits_frame.pack(fill="x", pady=5)
        
        Label(digits_frame, text="编号位数:", width=15).pack(side="left", padx=5)
        self.digits_entry = Entry(digits_frame, width=10)
        self.digits_entry.insert(0, str(self.number_digits))
        self.digits_entry.pack(side="left", padx=5)
        Label(digits_frame, text="(例如: 3位 = 001, 002...)").pack(side="left", padx=5)
        
        # 执行按钮
        button_frame = Frame(main_frame, pady=15)
        button_frame.pack(fill="x")
        
        Button(button_frame, text="预览重命名", command=self.preview_rename, font=("SimHei", 11), width=15).pack(side="left", padx=10)
        Button(button_frame, text="执行重命名", command=self.execute_rename, font=("SimHei", 11, "bold"), width=15, bg="#4CAF50", fg="white").pack(side="left", padx=10)
        
        # 结果显示
        result_frame = Frame(main_frame, pady=10)
        result_frame.pack(fill="both", expand=True)
        
        Label(result_frame, text="重命名结果:", font=("SimHei", 10, "bold")).pack(anchor="w")
        
        # 结果列表
        result_container = Frame(result_frame)
        result_container.pack(fill="both", expand=True)
        
        self.result_listbox = Listbox(result_container, width=80, height=8)
        self.result_listbox.pack(side="left", fill="both", expand=True)
        
        # 垂直滚动条
        rvscrollbar = Scrollbar(result_container, orient=VERTICAL, command=self.result_listbox.yview)
        rvscrollbar.pack(side="right", fill="y")
        self.result_listbox.config(yscrollcommand=rvscrollbar.set)
        
        # 水平滚动条
        rhscrollbar = Scrollbar(result_container, orient=HORIZONTAL, command=self.result_listbox.xview)
        rhscrollbar.pack(side="bottom", fill="x")
        self.result_listbox.config(xscrollcommand=rhscrollbar.set)
    
    def add_files(self):
        """通过对话框添加文件"""
        files = filedialog.askopenfilenames(title="选择文件")
        if files:
            for file_path in files:
                if file_path not in self.file_list:
                    self.file_list.append(file_path)
                    file_name = os.path.basename(file_path)
                    self.file_listbox.insert(END, f"{len(self.file_list)}. {file_name}")
            
            self.drop_label.config(text=f"📁 已添加 {len(self.file_list)} 个文件")
    
    def clear_list(self):
        """清空文件列表"""
        self.file_list.clear()
        self.file_listbox.delete(0, END)
        self.drop_label.config(text='📁 点击下方"添加文件"按钮选择文件')
    
    def move_up(self):
        """上移选中的文件"""
        selection = self.file_listbox.curselection()
        if not selection:
            return
        
        index = selection[0]
        if index == 0:
            return
        
        # 交换列表中的位置
        self.file_list[index], self.file_list[index-1] = self.file_list[index-1], self.file_list[index]
        
        # 更新显示
        self.refresh_listbox()
        self.file_listbox.selection_set(index-1)
    
    def move_down(self):
        """下移选中的文件"""
        selection = self.file_listbox.curselection()
        if not selection:
            return
        
        index = selection[0]
        if index == len(self.file_list) - 1:
            return
        
        # 交换列表中的位置
        self.file_list[index], self.file_list[index+1] = self.file_list[index+1], self.file_list[index]
        
        # 更新显示
        self.refresh_listbox()
        self.file_listbox.selection_set(index+1)
    
    def remove_selected(self):
        """移除选中的文件"""
        selection = self.file_listbox.curselection()
        if not selection:
            return
        
        index = selection[0]
        self.file_list.pop(index)
        self.refresh_listbox()
        
        if self.file_list:
            self.drop_label.config(text=f"📁 已添加 {len(self.file_list)} 个文件")
        else:
            self.drop_label.config(text='📁 点击下方"添加文件"按钮选择文件')
    
    def refresh_listbox(self):
        """刷新列表框显示"""
        self.file_listbox.delete(0, END)
        for i, file_path in enumerate(self.file_list, 1):
            file_name = os.path.basename(file_path)
            self.file_listbox.insert(END, f"{i}. {file_name}")
    
    def format_number(self, num, digits):
        """格式化数字，添加前导零"""
        return str(num).zfill(digits)
    
    def preview_rename(self):
        """预览重命名操作"""
        if not self.file_list:
            messagebox.showinfo("提示", "文件列表为空")
            return
        
        self.new_prefix = self.prefix_entry.get().strip()
        
        try:
            self.start_number = int(self.start_entry.get().strip())
            self.number_digits = int(self.digits_entry.get().strip())
            
            if self.start_number < 0:
                raise ValueError("起始编号不能为负数")
            if self.number_digits < 1:
                raise ValueError("编号位数必须大于0")
        except ValueError as e:
            messagebox.showerror("错误", f"参数设置错误: {e}")
            return
        
        # 清空结果列表
        self.result_listbox.delete(0, END)
        
        current_num = self.start_number
        
        for file_path in self.file_list:
            old_name = os.path.basename(file_path)
            ext = os.path.splitext(old_name)[1]
            formatted_num = self.format_number(current_num, self.number_digits)
            new_name = f"{self.new_prefix}{formatted_num}{ext}"
            
            self.result_listbox.insert(END, f"{old_name} -> {new_name}")
            current_num += 1
        
        messagebox.showinfo("预览", f"预览完成！\n共 {len(self.file_list)} 个文件将被重命名")
    
    def execute_rename(self):
        """执行重命名操作"""
        if not self.file_list:
            messagebox.showinfo("提示", "文件列表为空")
            return
        
        self.new_prefix = self.prefix_entry.get().strip()
        
        try:
            self.start_number = int(self.start_entry.get().strip())
            self.number_digits = int(self.digits_entry.get().strip())
            
            if self.start_number < 0:
                raise ValueError("起始编号不能为负数")
            if self.number_digits < 1:
                raise ValueError("编号位数必须大于0")
        except ValueError as e:
            messagebox.showerror("错误", f"参数设置错误: {e}")
            return
        
        # 确认操作
        confirm = messagebox.askyesno("确认", f"确定要重命名 {len(self.file_list)} 个文件吗？")
        if not confirm:
            return
        
        # 清空结果列表
        self.result_listbox.delete(0, END)
        
        success_count = 0
        skip_count = 0
        current_num = self.start_number
        
        for file_path in self.file_list:
            old_name = os.path.basename(file_path)
            ext = os.path.splitext(old_name)[1]
            formatted_num = self.format_number(current_num, self.number_digits)
            new_name = f"{self.new_prefix}{formatted_num}{ext}"
            
            # 获取文件所在目录
            dir_path = os.path.dirname(file_path)
            new_path = os.path.join(dir_path, new_name)
            
            if os.path.exists(new_path):
                if old_name.lower() != new_name.lower():
                    self.result_listbox.insert(END, f"[跳过] 目标已存在: {new_name}")
                    skip_count += 1
            else:
                try:
                    os.rename(file_path, new_path)
                    self.result_listbox.insert(END, f"[成功] {old_name} -> {new_name}")
                    success_count += 1
                except Exception as e:
                    self.result_listbox.insert(END, f"[失败] {old_name} - {e}")
                    skip_count += 1
            
            current_num += 1
        
        messagebox.showinfo("完成", f"重命名完成！\n成功: {success_count} 个\n失败/跳过: {skip_count} 个")
        
        # 清空列表
        self.clear_list()

def main():
    """主函数"""
    root = tk.Tk()
    app = BatchRenameApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()
