import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import random
import json
import os
import csv
from datetime import datetime
import time
import threading

class RandomPicker:
    def __init__(self, root):
        self.root = root
        self.root.title("🎯 随机抽签/点名器 v2.0")
        self.root.geometry("800x650")
        
        # 颜色方案
        self.colors = {
            'primary': '#2c3e50',
            'secondary': '#3498db',
            'success': '#2ecc71',
            'warning': '#f39c12',
            'danger': '#e74c3c',
            'light': '#ecf0f1',
            'dark': '#34495e',
            'highlight': '#e74c3c',
            'bg': '#f5f7fa'
        }
        
        # 数据
        self.names = []
        self.selected_history = []
        self.current_selection = None
        self.is_running = False
        self.animation_speed = 50  # 毫秒
        self.animation_timer = None
        
        # 创建界面
        self.create_widgets()
        
        # 加载数据
        self.load_data()
        
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 左侧面板
        left_frame = ttk.Frame(main_frame)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
        
        # 名单管理
        list_frame = ttk.LabelFrame(left_frame, text="📋 名单管理", padding=10)
        list_frame.pack(fill=tk.BOTH, expand=True)
        
        # 输入框
        input_frame = ttk.Frame(list_frame)
        input_frame.pack(fill=tk.X, pady=(0, 10))
        
        self.name_var = tk.StringVar()
        self.name_entry = ttk.Entry(input_frame, textvariable=self.name_var, 
                                   font=("微软雅黑", 11), width=25)
        self.name_entry.pack(side=tk.LEFT, padx=(0, 5))
        self.name_entry.bind('<Return>', lambda e: self.add_name())
        
        ttk.Button(input_frame, text="添加", command=self.add_name, 
                  width=8).pack(side=tk.LEFT, padx=2)
        
        # 批量导入按钮
        ttk.Button(input_frame, text="📂 导入", command=self.import_names, 
                  width=8).pack(side=tk.LEFT, padx=2)
        
        # 名单列表
        list_container = ttk.Frame(list_frame)
        list_container.pack(fill=tk.BOTH, expand=True)
        
        # 创建Treeview
        columns = ('index', 'name', 'status')
        self.names_tree = ttk.Treeview(list_container, columns=columns, show='headings', height=12)
        
        self.names_tree.heading('index', text='序号')
        self.names_tree.heading('name', text='姓名')
        self.names_tree.heading('status', text='状态')
        
        self.names_tree.column('index', width=50)
        self.names_tree.column('name', width=150)
        self.names_tree.column('status', width=80)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_container, orient=tk.VERTICAL, command=self.names_tree.yview)
        self.names_tree.configure(yscrollcommand=scrollbar.set)
        
        self.names_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 右键菜单
        self.create_context_menu()
        
        # 操作按钮
        btn_frame = ttk.Frame(list_frame)
        btn_frame.pack(fill=tk.X, pady=(10, 0))
        
        ttk.Button(btn_frame, text="🗑️ 删除选中", command=self.delete_selected, 
                  width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="🧹 清空全部", command=self.clear_all, 
                  width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="🔄 重置状态", command=self.reset_status, 
                  width=12).pack(side=tk.LEFT, padx=2)
        
        # 右侧面板
        right_frame = ttk.Frame(main_frame)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 抽签区域
        pick_frame = ttk.LabelFrame(right_frame, text="🎯 抽签区域", padding=20)
        pick_frame.pack(fill=tk.BOTH, expand=True)
        
        # 结果显示
        self.result_var = tk.StringVar(value="准备就绪")
        result_label = tk.Label(pick_frame, textvariable=self.result_var, 
                               font=("微软雅黑", 28, "bold"),
                               fg=self.colors['highlight'],
                               wraplength=300, justify='center')
        result_label.pack(expand=True, pady=30)
        
        # 状态信息
        self.status_var = tk.StringVar(value="名单人数: 0")
        tk.Label(pick_frame, textvariable=self.status_var, 
                font=("微软雅黑", 10), fg=self.colors['secondary']).pack()
        
        # 抽签按钮
        btn_frame = ttk.Frame(pick_frame)
        btn_frame.pack(pady=20)
        
        self.pick_btn = tk.Button(btn_frame, text="🎯 开始抽签", command=self.start_picking,
                                 bg=self.colors['danger'], fg='white',
                                 font=("微软雅黑", 16, "bold"),
                                 width=15, height=2)
        self.pick_btn.pack(pady=10)
        
        # 模式选择
        mode_frame = ttk.Frame(pick_frame)
        mode_frame.pack()
        
        self.mode_var = tk.StringVar(value="single")
        ttk.Radiobutton(mode_frame, text="单次抽取", variable=self.mode_var, 
                       value="single").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(mode_frame, text="多次抽取", variable=self.mode_var, 
                       value="multiple").pack(side=tk.LEFT, padx=5)
        
        # 抽取数量
        count_frame = ttk.Frame(pick_frame)
        count_frame.pack(pady=10)
        
        ttk.Label(count_frame, text="抽取数量:").pack(side=tk.LEFT, padx=5)
        self.count_var = tk.StringVar(value="1")
        self.count_spin = ttk.Spinbox(count_frame, from_=1, to=10, 
                                     textvariable=self.count_var, width=5)
        self.count_spin.pack(side=tk.LEFT, padx=5)
        
        # 选项
        options_frame = ttk.Frame(pick_frame)
        options_frame.pack(pady=10)
        
        self.repeat_var = tk.BooleanVar(value=False)
        ttk.Checkbutton(options_frame, text="允许重复抽取", 
                       variable=self.repeat_var).pack(side=tk.LEFT, padx=5)
        
        self.animation_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(options_frame, text="开启动画效果", 
                       variable=self.animation_var).pack(side=tk.LEFT, padx=5)
        
        # 历史记录
        history_frame = ttk.LabelFrame(right_frame, text="📜 抽取记录", padding=10)
        history_frame.pack(fill=tk.BOTH, expand=True, pady=(10, 0))
        
        columns = ('time', 'names')
        self.history_tree = ttk.Treeview(history_frame, columns=columns, show='headings', height=5)
        
        self.history_tree.heading('time', text='时间')
        self.history_tree.heading('names', text='抽取结果')
        
        self.history_tree.column('time', width=100)
        self.history_tree.column('names', width=250)
        
        scrollbar2 = ttk.Scrollbar(history_frame, orient=tk.VERTICAL, command=self.history_tree.yview)
        self.history_tree.configure(yscrollcommand=scrollbar2.set)
        
        self.history_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar2.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 导出按钮
        ttk.Button(history_frame, text="📤 导出记录", 
                  command=self.export_history).pack(pady=(5, 0))
        
    def create_context_menu(self):
        """创建右键菜单"""
        self.context_menu = tk.Menu(self.root, tearoff=0)
        self.context_menu.add_command(label="删除", command=self.delete_selected)
        self.context_menu.add_command(label="编辑", command=self.edit_name)
        self.context_menu.add_separator()
        self.context_menu.add_command(label="全选", command=self.select_all)
        
        self.names_tree.bind('<Button-3>', self.show_context_menu)
        
    def show_context_menu(self, event):
        """显示右键菜单"""
        self.context_menu.post(event.x_root, event.y_root)
        
    def add_name(self):
        """添加名字"""
        name = self.name_var.get().strip()
        if not name:
            messagebox.showwarning("警告", "请输入姓名！")
            return
            
        if name in self.names:
            messagebox.showwarning("警告", f"{name} 已存在！")
            return
            
        self.names.append(name)
        self.update_list_display()
        self.update_status()
        
        self.name_var.set("")
        self.name_entry.focus()
        self.save_data()
        
    def delete_selected(self):
        """删除选中项"""
        selected = self.names_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请选择要删除的项目！")
            return
            
        if messagebox.askyesno("确认", "确定要删除选中的项目吗？"):
            indices = []
            for item in selected:
                values = self.names_tree.item(item)['values']
                index = int(values[0]) - 1
                indices.append(index)
            
            # 从大到小删除，避免索引变化
            for index in sorted(indices, reverse=True):
                if index < len(self.names):
                    del self.names[index]
            
            self.update_list_display()
            self.update_status()
            self.save_data()
            
    def edit_name(self):
        """编辑名字"""
        selected = self.names_tree.selection()
        if not selected:
            return
            
        item = selected[0]
        values = self.names_tree.item(item)['values']
        index = int(values[0]) - 1
        
        # 创建编辑对话框
        dialog = tk.Toplevel(self.root)
        dialog.title("编辑姓名")
        dialog.geometry("300x150")
        
        tk.Label(dialog, text="请输入新姓名:", font=("微软雅黑", 12)).pack(pady=10)
        
        var = tk.StringVar(value=self.names[index])
        entry = ttk.Entry(dialog, textvariable=var, font=("微软雅黑", 12))
        entry.pack(pady=10)
        entry.select_range(0, tk.END)
        entry.focus()
        
        def save_edit():
            new_name = var.get().strip()
            if new_name:
                self.names[index] = new_name
                self.update_list_display()
                self.save_data()
                dialog.destroy()
                
        ttk.Button(dialog, text="保存", command=save_edit).pack()
        entry.bind('<Return>', lambda e: save_edit())
        
    def select_all(self):
        """全选"""
        self.names_tree.selection_set(self.names_tree.get_children())
        
    def clear_all(self):
        """清空全部"""
        if not self.names:
            return
            
        if messagebox.askyesno("确认", "确定要清空所有名单吗？"):
            self.names.clear()
            self.selected_history.clear()
            self.update_list_display()
            self.update_status()
            self.save_data()
            
    def reset_status(self):
        """重置状态"""
        self.selected_history.clear()
        self.update_list_display()
        self.save_data()
        
    def import_names(self):
        """导入名单"""
        filepath = filedialog.askopenfilename(
            title="选择文件",
            filetypes=[("文本文件", "*.txt"), ("CSV文件", "*.csv"), ("所有文件", "*.*")]
        )
        
        if not filepath:
            return
            
        try:
            new_names = []
            
            if filepath.endswith('.csv'):
                with open(filepath, 'r', encoding='utf-8') as f:
                    reader = csv.reader(f)
                    for row in reader:
                        if row:
                            new_names.extend([name.strip() for name in row if name.strip()])
            else:
                with open(filepath, 'r', encoding='utf-8') as f:
                    lines = f.readlines()
                    new_names = [line.strip() for line in lines if line.strip()]
            
            # 去重
            existing = set(self.names)
            added = 0
            for name in new_names:
                if name not in existing:
                    self.names.append(name)
                    existing.add(name)
                    added += 1
            
            self.update_list_display()
            self.update_status()
            self.save_data()
            
            messagebox.showinfo("成功", f"成功导入 {added} 个姓名！")
            
        except Exception as e:
            messagebox.showerror("错误", f"导入失败：{str(e)}")
            
    def start_picking(self):
        """开始抽签"""
        if not self.names:
            messagebox.showwarning("警告", "名单为空，请先添加姓名！")
            return
            
        if self.is_running:
            return
            
        # 获取可抽取的名单
        if self.repeat_var.get():
            available = self.names.copy()
        else:
            available = [name for name in self.names if name not in self.selected_history]
            
        if not available:
            messagebox.showinfo("提示", "所有人都已被抽取过！\n点击'重置状态'重新开始。")
            return
            
        # 获取抽取数量
        try:
            count = int(self.count_var.get())
        except:
            count = 1
            
        if count > len(available):
            count = len(available)
            
        self.is_running = True
        self.pick_btn.config(state='disabled', text="抽签中...")
        
        if self.animation_var.get():
            # 动画抽取
            self.animate_picking(available, count)
        else:
            # 直接抽取
            self.do_pick(available, count)
            
    def animate_picking(self, available, count):
        """动画抽取"""
        if count == 1:
            # 单次抽取动画
            self.animate_single(available)
        else:
            # 多次抽取
            self.do_pick(available, count)
            
    def animate_single(self, available):
        """单次抽取动画"""
        if not hasattr(self, '_anim_count'):
            self._anim_count = 0
            self._anim_max = 20 + random.randint(5, 15)
            
        if self._anim_count < self._anim_max:
            # 随机显示名字
            name = random.choice(available)
            self.result_var.set(name)
            self._anim_count += 1
            self.root.after(self.animation_speed, self.animate_single, available)
        else:
            # 最终结果
            self._anim_count = 0
            self.do_pick(available, 1)
            
    def do_pick(self, available, count):
        """执行抽取"""
        # 随机选择
        selected = random.sample(available, min(count, len(available)))
        
        # 更新历史
        if not self.repeat_var.get():
            self.selected_history.extend(selected)
            
        # 显示结果
        if len(selected) == 1:
            self.result_var.set(f"🎉 {selected[0]}")
        else:
            result_text = "\n".join([f"  {i+1}. {name}" for i, name in enumerate(selected)])
            self.result_var.set(f"🎉 抽取结果：\n{result_text}")
        
        # 添加历史记录
        timestamp = datetime.now().strftime('%H:%M:%S')
        names_text = ", ".join(selected)
        self.history_tree.insert('', 'end', values=(timestamp, names_text))
        
        # 更新列表显示
        self.update_list_display()
        
        # 重置状态
        self.is_running = False
        self.pick_btn.config(state='normal', text="🎯 开始抽签")
        
        # 保存数据
        self.save_data()
        
    def update_list_display(self):
        """更新列表显示"""
        for item in self.names_tree.get_children():
            self.names_tree.delete(item)
            
        for i, name in enumerate(self.names, 1):
            status = "✅ 已抽" if name in self.selected_history else "⬜ 未抽"
            self.names_tree.insert('', 'end', values=(i, name, status))
            
    def update_status(self):
        """更新状态信息"""
        total = len(self.names)
        picked = len(self.selected_history)
        remaining = total - picked
        self.status_var.set(f"名单人数: {total} | 已抽: {picked} | 剩余: {remaining}")
        
    def export_history(self):
        """导出历史记录"""
        if not self.history_tree.get_children():
            messagebox.showinfo("提示", "暂无记录可导出！")
            return
            
        filepath = filedialog.asksaveasfilename(
            defaultextension='.txt',
            filetypes=[("文本文件", "*.txt"), ("CSV文件", "*.csv"), ("所有文件", "*.*")]
        )
        
        if not filepath:
            return
            
        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                f.write("随机抽签/点名记录\n")
                f.write(f"导出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write("=" * 40 + "\n\n")
                
                for item in self.history_tree.get_children():
                    values = self.history_tree.item(item)['values']
                    f.write(f"[{values[0]}] {values[1]}\n")
                    
            messagebox.showinfo("成功", f"记录已导出到：{filepath}")
            
        except Exception as e:
            messagebox.showerror("错误", f"导出失败：{str(e)}")
            
    def save_data(self):
        """保存数据"""
        data = {
            'names': self.names,
            'selected_history': self.selected_history
        }
        
        try:
            with open('picker_data.json', 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except:
            pass
            
    def load_data(self):
        """加载数据"""
        try:
            if os.path.exists('picker_data.json'):
                with open('picker_data.json', 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    
                self.names = data.get('names', [])
                self.selected_history = data.get('selected_history', [])
                
                self.update_list_display()
                self.update_status()
        except:
            pass

# 运行程序
if __name__ == "__main__":
    root = tk.Tk()
    app = RandomPicker(root)
    root.mainloop()