import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk, ImageDraw, ImageFont
import qrcode
import os


class StudentIDGeneratorGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("学生证件生成器")
        self.root.geometry("1000x700")

        self.photo_path = None
        self.preview_image = None

        self.setup_ui()

    def setup_ui(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 左侧：信息输入区域
        info_frame = ttk.LabelFrame(main_frame, text="学生信息", padding="10")
        info_frame.grid(row=0, column=0, padx=10,
                        sticky=(tk.W, tk.E, tk.N, tk.S))

        # 输入字段
        fields = [
            ("姓名:", "name_var", ""),
            ("学号:", "sid_var", ""),
            ("性别:", "gender_var", ""),
            ("班级:", "class_var", ""),
            ("出生日期:", "birth_var", "YYYY-MM-DD"),
            ("联系电话:", "phone_var", ""),
            ("有效期限:", "valid_var", "2024-2028"),
        ]

        self.entries = {}
        for i, (label, var_name, placeholder) in enumerate(fields):
            ttk.Label(info_frame, text=label).grid(
                row=i, column=0, sticky=tk.W, pady=5)
            var = tk.StringVar()
            setattr(self, var_name, var)
            entry = ttk.Entry(info_frame, textvariable=var, width=25)
            entry.grid(row=i, column=1, padx=10, pady=5)
            if placeholder:
                entry.insert(0, placeholder)
            self.entries[label] = entry

        # 照片选择
        ttk.Label(info_frame, text="照片:").grid(
            row=len(fields), column=0, sticky=tk.W, pady=5)
        self.photo_label = ttk.Label(
            info_frame, text="未选择照片", foreground="gray")
        self.photo_label.grid(row=len(fields), column=1, padx=10, pady=5)

        ttk.Button(info_frame, text="选择照片", command=self.select_photo).grid(
            row=len(fields)+1, column=0, columnspan=2, pady=5)

        # 按钮
        button_frame = ttk.Frame(info_frame)
        button_frame.grid(row=len(fields)+2, column=0, columnspan=2, pady=20)

        ttk.Button(button_frame, text="生成预览", command=self.preview_card).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="保存证件", command=self.save_card).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="批量生成", command=self.batch_generate).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="清空表单", command=self.clear_form).pack(
            side=tk.LEFT, padx=5)

        # 右侧：预览区域
        preview_frame = ttk.LabelFrame(main_frame, text="预览", padding="10")
        preview_frame.grid(row=0, column=1, padx=10,
                           sticky=(tk.W, tk.E, tk.N, tk.S))

        self.preview_canvas = tk.Canvas(
            preview_frame, width=450, height=300, bg='white')
        self.preview_canvas.pack()

        # 批量生成窗口
        self.batch_window = None

    def select_photo(self):
        file_path = filedialog.askopenfilename(
            title="选择学生照片",
            filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp")]
        )
        if file_path:
            self.photo_path = file_path
            self.photo_label.config(text=os.path.basename(
                file_path), foreground="green")

    def generate_card(self, student_info, output_path):
        """生成学生证图片"""
        card_width, card_height = 900, 600
        img = Image.new('RGB', (card_width, card_height), (255, 255, 255))
        draw = ImageDraw.Draw(img)

        # 加载字体
        try:
            font_title = ImageFont.truetype("simhei.ttf", 36)
            font_normal = ImageFont.truetype("simhei.ttf", 24)
            font_small = ImageFont.truetype("simhei.ttf", 18)
        except:
            font_title = font_normal = font_small = ImageFont.load_default()

        # 绘制边框和标题
        draw.rectangle([10, 10, card_width-10, card_height-10],
                       outline=(0, 100, 200), width=3)
        title = "学 生 证"
        title_width = draw.textlength(title, font=font_title)
        draw.text(((card_width - title_width) // 2, 30),
                  title, fill=(0, 70, 150), font=font_title)
        draw.line([50, 80, card_width-50, 80], fill=(200, 200, 200), width=2)

        # 照片区域
        photo_x, photo_y = 50, 110
        photo_width, photo_height = 200, 240
        draw.rectangle([photo_x, photo_y, photo_x+photo_width, photo_y+photo_height],
                       outline=(200, 200, 200), width=2)

        # 粘贴照片
        if student_info.get('photo_path') and os.path.exists(student_info['photo_path']):
            try:
                photo = Image.open(student_info['photo_path'])
                photo = photo.resize(
                    (photo_width, photo_height), Image.Resampling.LANCZOS)
                img.paste(photo, (photo_x, photo_y))
            except:
                draw.text((photo_x+50, photo_y+100), "照片加载失败",
                          fill=(150, 150, 150), font=font_small)
        else:
            draw.text((photo_x+50, photo_y+100), "照 片",
                      fill=(150, 150, 150), font=font_normal)

        # 学生信息
        info_x = photo_x + photo_width + 40
        info_y = 120
        line_height = 35

        info_items = [
            (f"姓    名：{student_info.get('name', '')}", font_normal),
            (f"性    别：{student_info.get('gender', '')}", font_normal),
            (f"学    号：{student_info.get('student_id', '')}", font_normal),
            (f"班    级：{student_info.get('class', '')}", font_normal),
            (f"出生日期：{student_info.get('birth_date', '')}", font_normal),
            (f"联系电话：{student_info.get('phone', '')}", font_normal),
            (f"有效期限：{student_info.get('valid_date', '')}", font_small),
        ]

        for i, (text, font) in enumerate(info_items):
            draw.text((info_x, info_y + i * line_height),
                      text, fill=(50, 50, 50), font=font)

        # 生成二维码
        qr_data = f"姓名:{student_info.get('name')}\n学号:{student_info.get('student_id')}\n班级:{student_info.get('class')}"
        qr = qrcode.QRCode(box_size=4, border=2)
        qr.add_data(qr_data)
        qr.make(fit=True)
        qr_img = qr.make_image(fill_color="black", back_color="white")
        qr_img = qr_img.resize((120, 120))

        qr_x = card_width - 150
        qr_y = card_height - 150
        img.paste(qr_img, (qr_x, qr_y))

        draw.text((50, card_height - 40), "XX大学学生证   此证仅限本人使用",
                  fill=(150, 150, 150), font=font_small)

        img.save(output_path)
        return output_path

    def preview_card(self):
        """预览学生证"""
        student_info = self.get_student_info()
        if not student_info['name']:
            messagebox.showwarning("警告", "请至少填写学生姓名")
            return

        # 生成临时预览图片
        temp_path = "temp_preview.png"
        self.generate_card(student_info, temp_path)

        # 显示预览
        preview_img = Image.open(temp_path)
        preview_img.thumbnail((450, 300), Image.Resampling.LANCZOS)

        self.preview_image = ImageTk.PhotoImage(preview_img)
        self.preview_canvas.delete("all")
        self.preview_canvas.create_image(225, 150, image=self.preview_image)

        # 删除临时文件
        if os.path.exists(temp_path):
            os.remove(temp_path)

    def save_card(self):
        """保存学生证"""
        student_info = self.get_student_info()
        if not student_info['name']:
            messagebox.showwarning("警告", "请至少填写学生姓名")
            return

        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG文件", "*.png"),
                       ("JPEG文件", "*.jpg"), ("所有文件", "*.*")],
            initialfile=f"{student_info['name']}_学生证.png"
        )

        if file_path:
            self.generate_card(student_info, file_path)
            messagebox.showinfo("成功", f"学生证已保存到：{file_path}")

    def get_student_info(self):
        """获取表单中的学生信息"""
        return {
            'name': self.name_var.get(),
            'student_id': self.sid_var.get(),
            'gender': self.gender_var.get(),
            'class': self.class_var.get(),
            'birth_date': self.birth_var.get(),
            'phone': self.phone_var.get(),
            'valid_date': self.valid_var.get(),
            'photo_path': self.photo_path if self.photo_path else None
        }

    def clear_form(self):
        """清空表单"""
        self.name_var.set("")
        self.sid_var.set("")
        self.gender_var.set("")
        self.class_var.set("")
        self.birth_var.set("")
        self.phone_var.set("")
        self.valid_var.set("2024-2028")
        self.photo_path = None
        self.photo_label.config(text="未选择照片", foreground="gray")
        self.preview_canvas.delete("all")

    def batch_generate(self):
        """批量生成窗口"""
        if self.batch_window and self.batch_window.winfo_exists():
            self.batch_window.lift()
            return

        self.batch_window = tk.Toplevel(self.root)
        self.batch_window.title("批量生成学生证")
        self.batch_window.geometry("600x500")

        # 批量输入区域
        ttk.Label(self.batch_window,
                  text="批量学生信息（每行一个，格式：姓名,学号,班级,性别）").pack(pady=10)

        text_frame = ttk.Frame(self.batch_window)
        text_frame.pack(pady=5, padx=10, fill=tk.BOTH, expand=True)

        self.batch_text = tk.Text(text_frame, height=15, width=70)
        self.batch_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(
            text_frame, orient="vertical", command=self.batch_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.batch_text.configure(yscrollcommand=scrollbar.set)

        # 示例文本
        example = """示例（请按此格式输入）：
张三,20240001,计算机1班,男
李四,20240002,软件2班,女
王五,20240003,人工智能1班,男"""
        self.batch_text.insert("1.0", example)

        # 按钮
        btn_frame = ttk.Frame(self.batch_window)
        btn_frame.pack(pady=10)

        ttk.Button(btn_frame, text="选择照片目录", command=self.select_photo_dir).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="开始批量生成", command=self.do_batch_generate).pack(
            side=tk.LEFT, padx=5)

        self.photo_dir = tk.StringVar()
        ttk.Label(self.batch_window, textvariable=self.photo_dir,
                  foreground="blue").pack(pady=5)

    def select_photo_dir(self):
        """选择照片目录"""
        dir_path = filedialog.askdirectory(title="选择学生照片目录（照片文件名应为：学号.jpg）")
        if dir_path:
            self.photo_dir.set(dir_path)

    def do_batch_generate(self):
        """执行批量生成"""
        text_content = self.batch_text.get("1.0", tk.END).strip()
        lines = text_content.split('\n')

        # 创建输出目录
        output_dir = "student_cards"
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        success_count = 0
        for line in lines:
            if line.startswith('#') or not line.strip():
                continue

            parts = [p.strip() for p in line.split(',')]
            if len(parts) >= 3:
                student = {
                    'name': parts[0],
                    'student_id': parts[1],
                    'class': parts[2] if len(parts) > 2 else "",
                    'gender': parts[3] if len(parts) > 3 else "",
                    'birth_date': "2000-01-01",
                    'phone': "未填写",
                    'valid_date': "2024-2028",
                    'photo_path': None
                }

                # 查找照片
                if self.photo_dir.get():
                    photo_path = os.path.join(
                        self.photo_dir.get(), f"{student['student_id']}.jpg")
                    if os.path.exists(photo_path):
                        student['photo_path'] = photo_path
                    else:
                        # 尝试其他格式
                        for ext in ['.png', '.jpeg', '.bmp']:
                            photo_path = os.path.join(
                                self.photo_dir.get(), f"{student['student_id']}{ext}")
                            if os.path.exists(photo_path):
                                student['photo_path'] = photo_path
                                break

                output_path = os.path.join(
                    output_dir, f"{student['name']}_{student['student_id']}_学生证.png")
                self.generate_card(student, output_path)
                success_count += 1

        messagebox.showinfo(
            "完成", f"批量生成完成！\n成功生成 {success_count} 个学生证\n保存在 {output_dir} 目录")


# 运行程序
if __name__ == "__main__":
    root = tk.Tk()
    app = StudentIDGeneratorGUI(root)
    root.mainloop()
