import tkinter as tk
from tkinter import ttk, messagebox
import json
from datetime import datetime
import os

# 数据保存文件
DATA_FILE = "birthday_data.json"

class BirthdayReminder:
    def __init__(self, root):
        self.root = root
        self.root.title("生日提醒器")
        self.root.geometry("520x420")

        # 加载数据
        self.birthdays = self.load_data()

        # 创建界面
        self.create_widgets()
        self.refresh_list()
        self.check_coming_birthday()

    def load_data(self):
        if os.path.exists(DATA_FILE):
            try:
                with open(DATA_FILE, "r", encoding="utf-8") as f:
                    return json.load(f)
            except:
                return []
        return []

    def save_data(self):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(self.birthdays, f, ensure_ascii=False, indent=2)

    def create_widgets(self):
        # 输入区域
        frame_input = tk.Frame(self.root, pady=8)
        frame_input.pack(fill="x", padx=10)

        tk.Label(frame_input, text="姓名：").grid(row=0, column=0, sticky="w")
        self.var_name = tk.StringVar()
        tk.Entry(frame_input, textvariable=self.var_name, width=12).grid(row=0, column=1, padx=4)

        tk.Label(frame_input, text="日期(月-日)：").grid(row=0, column=2, sticky="w")
        self.var_date = tk.StringVar()
        tk.Entry(frame_input, textvariable=self.var_date, width=10).grid(row=0, column=3, padx=4)

        tk.Label(frame_input, text="备注：").grid(row=1, column=0, sticky="w", pady=4)
        self.var_note = tk.StringVar()
        tk.Entry(frame_input, textvariable=self.var_note, width=32).grid(row=1, column=1, columnspan=3, padx=4)

        # 按钮区域
        frame_btn = tk.Frame(self.root, pady=5)
        frame_btn.pack()
        tk.Button(frame_btn, text="添加生日", command=self.add_birthday).grid(row=0, column=0, padx=5)
        tk.Button(frame_btn, text="删除选中", command=self.del_birthday).grid(row=0, column=1, padx=5)
        tk.Button(frame_btn, text="刷新列表", command=self.refresh_list).grid(row=0, column=2, padx=5)

        # 表格列表
        frame_table = tk.Frame(self.root)
        frame_table.pack(fill="both", expand=True, padx=10, pady=5)

        columns = ("name", "date", "days", "note")
        self.tree = ttk.Treeview(frame_table, columns=columns, show="headings")
        self.tree.heading("name", text="姓名")
        self.tree.heading("date", text="生日(月-日)")
        self.tree.heading("days", text="距离天数")
        self.tree.heading("note", text="备注")

        self.tree.column("name", width=90)
        self.tree.column("date", width=90)
        self.tree.column("days", width=80)
        self.tree.column("note", width=200)

        scroll = ttk.Scrollbar(frame_table, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=scroll.set)
        self.tree.pack(side="left", fill="both", expand=True)
        scroll.pack(side="right", fill="y")

    # 计算距离下一次生日天数
    def get_days_remaining(self, month_day):
        try:
            m, d = map(int, month_day.split("-"))
            today = datetime.now()
            next_birth = datetime(year=today.year, month=m, day=d)
            if next_birth < today:
                next_birth = datetime(year=today.year+1, month=m, day=d)
            diff = (next_birth - today).days
            return diff
        except:
            return -1

    def add_birthday(self):
        name = self.var_name.get().strip()
        date = self.var_date.get().strip()
        note = self.var_note.get().strip()
        if not name or not date:
            messagebox.showwarning("提示", "姓名和生日日期不能为空！格式：月-日，例如 10-01")
            return
        if self.get_days_remaining(date) == -1:
            messagebox.showerror("错误", "日期格式错误！请使用 月-日 如 05-20")
            return
        self.birthdays.append({"name": name, "date": date, "note": note})
        self.save_data()
        self.refresh_list()
        # 清空输入框
        self.var_name.set("")
        self.var_date.set("")
        self.var_note.set("")

    def del_birthday(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showinfo("提示", "请先选中一条记录")
            return
        idx = self.tree.index(selected[0])
        del self.birthdays[idx]
        self.save_data()
        self.refresh_list()

    def refresh_list(self):
        # 清空表格
        for item in self.tree.get_children():
            self.tree.delete(item)
        # 重新填充
        for info in self.birthdays:
            days = self.get_days_remaining(info["date"])
            self.tree.insert("", "end", values=(info["name"], info["date"], f"{days}天", info["note"]))

    def check_coming_birthday(self):
        # 检测7天内生日，弹窗提醒
        coming = []
        for info in self.birthdays:
            days = self.get_days_remaining(info["date"])
            if 0 <= days <= 7:
                coming.append(f"{info['name']}，还有{days}天过生日")
        if coming:
            msg = "🔔近期生日提醒：\n" + "\n".join(coming)
            messagebox.showinfo("生日提醒", msg)

if __name__ == "__main__":
    root = tk.Tk()
    app = BirthdayReminder(root)
    root.mainloop()