import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox, filedialog
import random
import json
import os

root = tk.Tk()
root.title("🎯 多功能抽签 / 随机点名器")
root.geometry("560x560")
root.resizable(False, False)

NAMES_FILE = "name_list.json"
history = []


def load_names():
    if os.path.exists(NAMES_FILE):
        try:
            with open(NAMES_FILE, "r", encoding="utf-8") as f:
                d = json.load(f)
                if isinstance(d, list):
                    return [n for n in d if isinstance(n, str) and n.strip()]
        except:
            pass
    return ["张三", "李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十",
            "刘一", "陈二", "杨十一", "黄十二"]


def save_names():
    with open(NAMES_FILE, "w", encoding="utf-8") as f:
        json.dump(name_list, f, ensure_ascii=False, indent=2)


name_list = load_names()
used_set = set()


count_var = tk.IntVar(value=1)
mode_var = tk.StringVar(value="点名模式")
dup_var = tk.BooleanVar(value=False)
result_var = tk.StringVar(value="点击「开始抽签」")
status_var = tk.StringVar(value=f"名单共 {len(name_list)} 人")


def do_roll():
    mode = mode_var.get()
    count = count_var.get()
    allow_dup = dup_var.get()

    pool = list(name_list)
    if not pool:
        result_var.set("名单为空，请先添加名字")
        return

    if not allow_dup:
        remain = [n for n in pool if n not in used_set]
        if not remain:
            result_var.set("所有人都已点过，已自动重置")
            used_set.clear()
            remain = pool
    else:
        remain = pool

    if count < 1:
        count = 1
    if count > len(remain):
        count = len(remain)

    picked = random.sample(remain, count)
    for n in picked:
        used_set.add(n)

    if mode == "点名模式":
        res = f"🎉 点到：{picked[0]}" if count == 1 else "🎉 点到 " + str(count) + " 人：\n" + "、".join(picked)
    else:
        res = "🎯 抽签结果：\n" + "、".join(picked)

    result_var.set(res)
    history.append(picked)
    refresh_history()
    status_var.set(f"名单共 {len(name_list)} 人 | 已点 {len(used_set)} 人")


def reset_used():
    used_set.clear()
    status_var.set(f"名单共 {len(name_list)} 人 | 已重置已点记录")
    result_var.set("已点记录已清空")


def add_name():
    n = name_entry.get().strip()
    if not n:
        return
    if n in name_list:
        result_var.set(f"「{n}」已在名单中")
        return
    name_list.append(n)
    save_names()
    refresh_listbox()
    name_entry.delete(0, "end")
    status_var.set(f"名单共 {len(name_list)} 人")


def remove_selected():
    sel = listbox.curselection()
    if not sel:
        return
    for idx in reversed(sel):
        name_list.pop(idx)
    save_names()
    refresh_listbox()
    status_var.set(f"名单共 {len(name_list)} 人")


def refresh_listbox():
    listbox.delete(0, "end")
    for n in name_list:
        mark = "  ✔" if n in used_set else ""
        listbox.insert("end", n + mark)


def import_from_file():
    path = filedialog.askopenfilename(filetypes=[("文本文件", "*.txt"), ("JSON", "*.json"), ("所有文件", "*.*")])
    if not path:
        return
    try:
        if path.endswith(".json"):
            with open(path, "r", encoding="utf-8") as f:
                data = json.load(f)
            new_names = [n for n in data if isinstance(n, str) and n.strip()]
        else:
            with open(path, "r", encoding="utf-8") as f:
                new_names = [line.strip() for line in f if line.strip()]
        added = 0
        for n in new_names:
            if n not in name_list:
                name_list.append(n)
                added += 1
        save_names()
        refresh_listbox()
        status_var.set(f"名单共 {len(name_list)} 人 | 本次导入 {added} 人")
    except Exception as e:
        messagebox.showerror("导入失败", str(e))


def refresh_history():
    hist_text.config(state="normal")
    hist_text.delete("1.0", "end")
    for i, h in enumerate(reversed(history[-50:]), 1):
        hist_text.insert("end", f"{i}. {'、'.join(h)}\n")
    hist_text.config(state="disabled")


def clear_history():
    history.clear()
    refresh_history()


ttk.Label(root, text="🎯 多功能抽签 / 随机点名器",
          font=("Microsoft YaHei", 15, "bold")).pack(pady=8)

topf = ttk.Frame(root)
topf.pack(pady=2, padx=15, fill="x")
ttk.Label(topf, text="模式：").pack(side="left")
ttk.Radiobutton(topf, text="点名模式", variable=mode_var, value="点名模式").pack(side="left", padx=5)
ttk.Radiobutton(topf, text="抽签模式", variable=mode_var, value="抽签模式").pack(side="left", padx=5)
ttk.Label(topf, text="  抽取数量：").pack(side="left")
ttk.Spinbox(topf, from_=1, to=50, textvariable=count_var, width=5).pack(side="left", padx=3)
ttk.Checkbutton(topf, text="可重复", variable=dup_var).pack(side="left", padx=10)

res_frame = tk.Frame(root, bg="#fff8e1", highlightbackground="#ffd54f", highlightthickness=2)
res_frame.pack(pady=8, padx=20, fill="x")
tk.Label(res_frame, textvariable=result_var, font=("Microsoft YaHei", 13, "bold"),
         fg="#d32f2f", bg="#fff8e1", wraplength=480, justify="center").pack(pady=10)

btf = ttk.Frame(root)
btf.pack(pady=2)
ttk.Button(btf, text="🎰 开始抽签", command=do_roll).pack(side="left", padx=6)
ttk.Button(btf, text="🔄 重置已点记录", command=reset_used).pack(side="left", padx=6)

list_frame = ttk.LabelFrame(root, text="名单管理")
list_frame.pack(pady=6, padx=15, fill="both", expand=True)

inf = ttk.Frame(list_frame)
inf.pack(pady=4, padx=8, fill="x")
name_entry = ttk.Entry(inf, font=("Microsoft YaHei", 10))
name_entry.pack(side="left", fill="x", expand=True, padx=(0, 5))
ttk.Button(inf, text="添加", command=add_name).pack(side="left", padx=2)
ttk.Button(inf, text="删除选中", command=remove_selected).pack(side="left", padx=2)
ttk.Button(inf, text="导入文件", command=import_from_file).pack(side="left", padx=2)

listbox = tk.Listbox(list_frame, height=6, font=("Microsoft YaHei", 10), selectmode="extended")
listbox.pack(padx=8, pady=4, fill="both", expand=True)
refresh_listbox()

hist_frame = ttk.LabelFrame(root, text="点名历史（最近50条）")
hist_frame.pack(pady=6, padx=15, fill="both", expand=True)
hist_text = scrolledtext.ScrolledText(hist_frame, height=5, font=("Microsoft YaHei", 9), state="disabled")
hist_text.pack(padx=5, pady=4, fill="both", expand=True)
ttk.Button(hist_frame, text="清空历史", command=clear_history).pack(pady=2)

ttk.Label(root, textvariable=status_var, font=("Microsoft YaHei", 9), foreground="#666").pack(pady=4)

name_entry.bind("<Return>", lambda e: add_name())

root.mainloop()