import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageDraw, ImageFont, ImageOps
import os
import datetime


class StudentIDGenerator:
    def __init__(self, root):
        self.root = root
        self.root.title("学生证件生成工具")
        self.root.geometry("500x600")
        self.root.resizable(False, False)

        # 存储用户输入
        self.user_data = {
            "name": tk.StringVar(),
            "student_id": tk.StringVar(),
            "college": tk.StringVar(),
            "major": tk.StringVar(),
            "enrollment_year": tk.StringVar(),
            "photo_path": tk.StringVar(),
            # 默认4年有效期
            "valid_until": tk.StringVar(value=f"{datetime.datetime.now().year + 4}-06")
        }

        # 证件模板参数（像素尺寸：1000x630，类似银行卡比例）
        self.id_width = 1000
        self.id_height = 630
        self.photo_size = (280, 350)  # 证件照尺寸（小一寸比例）
        self.font_path = self._get_font_path()  # 获取中文字体路径

        self._create_widgets()

    def _get_font_path(self):
        """获取系统中文字体路径（兼容Windows/macOS/Linux）"""
        possible_paths = [
            "C:/Windows/Fonts/simhei.ttf",  # Windows黑体
            "/System/Library/Fonts/PingFang.ttc",  # macOS苹方
            "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",  # Linux文泉驿微米黑
            "./simhei.ttf"  # 当前目录备用字体
        ]
        for path in possible_paths:
            if os.path.exists(path):
                return path
        messagebox.showwarning("字体缺失", "未找到中文字体，可能导致中文显示异常")
        return None

    def _create_widgets(self):
        """创建GUI输入组件"""
        # 标题
        title_label = tk.Label(self.root, text="学生证件生成",
                               font=("Arial", 16, "bold"))
        title_label.pack(pady=10)

        # 输入框框架
        input_frame = tk.Frame(self.root)
        input_frame.pack(padx=20, pady=10, fill="both", expand=True)

        # 姓名
        tk.Label(input_frame, text="姓名:").grid(
            row=0, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["name"], width=30).grid(
            row=0, column=1, pady=5)

        # 学号
        tk.Label(input_frame, text="学号:").grid(
            row=1, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["student_id"], width=30).grid(
            row=1, column=1, pady=5)

        # 学院
        tk.Label(input_frame, text="学院:").grid(
            row=2, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["college"], width=30).grid(
            row=2, column=1, pady=5)

        # 专业
        tk.Label(input_frame, text="专业:").grid(
            row=3, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["major"], width=30).grid(
            row=3, column=1, pady=5)

        # 入学年份
        tk.Label(input_frame, text="入学年份:").grid(
            row=4, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["enrollment_year"], width=30).grid(
            row=4, column=1, pady=5)

        # 有效期
        tk.Label(input_frame, text="有效期至:").grid(
            row=5, column=0, sticky="w", pady=5)
        tk.Entry(input_frame, textvariable=self.user_data["valid_until"], width=30).grid(
            row=5, column=1, pady=5)

        # 照片上传
        tk.Label(input_frame, text="证件照:").grid(
            row=6, column=0, sticky="w", pady=5)
        photo_frame = tk.Frame(input_frame)
        photo_frame.grid(row=6, column=1, sticky="w", pady=5)
        tk.Entry(photo_frame, textvariable=self.user_data["photo_path"], width=25, state="readonly").pack(
            side="left")
        tk.Button(photo_frame, text="选择照片", command=self._select_photo).pack(
            side="left", padx=5)

        # 生成按钮
        generate_btn = tk.Button(
            self.root, text="生成学生证", command=self._generate_id,
            bg="#4CAF50", fg="white", font=("Arial", 12, "bold"), padx=20, pady=5
        )
        generate_btn.pack(pady=20)

    def _select_photo(self):
        """打开文件对话框选择证件照"""
        file_path = filedialog.askopenfilename(
            title="选择证件照",
            filetypes=[("图片文件", "*.jpg;*.jpeg;*.png")]
        )
        if file_path:
            self.user_data["photo_path"].set(file_path)

    def _generate_id(self):
        """核心：合成学生证件图片"""
        # 校验输入
        required_fields = ["name", "student_id", "college",
                           "major", "enrollment_year", "photo_path"]
        for field in required_fields:
            if not self.user_data[field].get():
                messagebox.showerror("输入错误", f"请填写{field}信息！")
                return

        try:
            # 1. 创建证件背景（浅蓝色渐变）
            bg = Image.new("RGB", (self.id_width, self.id_height), "#E8F4FF")
            draw = ImageDraw.Draw(bg)

            # 2. 添加顶部校名（示例："XX大学"）
            if self.font_path:
                title_font = ImageFont.truetype(self.font_path, 48)
            else:
                title_font = ImageFont.load_default()
            draw.text((self.id_width//2, 50), "XX大学学生证",
                      font=title_font, fill="#003366", anchor="mm")

            # 3. 粘贴证件照（居中偏左）
            photo = Image.open(
                self.user_data["photo_path"].get()).convert("RGB")
            photo = photo.resize(self.photo_size, Image.LANCZOS)  # 高质量缩放
            photo_pos = (80, (self.id_height - self.photo_size[1])//2)
            bg.paste(photo, photo_pos)

            # 4. 绘制个人信息（右侧区域）
            info_x = photo_pos[0] + self.photo_size[0] + 50
            info_y = photo_pos[1]
            line_height = 50

            # 字体设置
            if self.font_path:
                name_font = ImageFont.truetype(self.font_path, 36)
                info_font = ImageFont.truetype(self.font_path, 28)
                small_font = ImageFont.truetype(self.font_path, 24)
            else:
                name_font = info_font = small_font = ImageFont.load_default()

            # 姓名（加粗突出）
            draw.text(
                (info_x, info_y), f"姓名：{self.user_data['name'].get()}", font=name_font, fill="#000000")
            info_y += line_height

            # 学号
            draw.text(
                (info_x, info_y), f"学号：{self.user_data['student_id'].get()}", font=info_font, fill="#333333")
            info_y += line_height

            # 学院
            draw.text(
                (info_x, info_y), f"学院：{self.user_data['college'].get()}", font=info_font, fill="#333333")
            info_y += line_height

            # 专业
            draw.text(
                (info_x, info_y), f"专业：{self.user_data['major'].get()}", font=info_font, fill="#333333")
            info_y += line_height

            # 入学年份
            draw.text(
                (info_x, info_y), f"入学年份：{self.user_data['enrollment_year'].get()}", font=info_font, fill="#333333")
            info_y += line_height

            # 有效期
            draw.text(
                (info_x, info_y), f"有效期至：{self.user_data['valid_until'].get()}", font=info_font, fill="#333333")
            info_y += line_height * 2

            # 5. 添加底部防伪信息（右下角）
            watermark_font = small_font
            draw.text((self.id_width - 200, self.id_height - 50),
                      "XX大学教务处制", font=watermark_font, fill="#999999")
            draw.text((self.id_width - 200, self.id_height - 30), datetime.datetime.now(
            ).strftime("%Y-%m-%d"), font=watermark_font, fill="#999999")

            # 6. 添加边框
            draw.rectangle(
                [(0, 0), (self.id_width-1, self.id_height-1)], outline="#003366", width=4)

            # 7. 保存图片
            save_path = filedialog.asksaveasfilename(
                defaultextension=".jpg",
                filetypes=[("JPG图片", "*.jpg"), ("PNG图片", "*.png")],
                title="保存学生证"
            )
            if save_path:
                bg.save(save_path, quality=95)
                messagebox.showinfo("成功", f"学生证已保存至：\n{save_path}")

        except Exception as e:
            messagebox.showerror("生成失败", f"错误原因：{str(e)}")


if __name__ == "__main__":
    root = tk.Tk()
    app = StudentIDGenerator(root)
    root.mainloop()
