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

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

class BirthdayReminder:
    def __init__(self, root):
        self.root = root
        self.root.title("生日提醒器")
        self.root.geometry("620x450")
        self.root.resizable(False, False)

        # 加载本地生日数据
        self.birthdays = self.load_data()

        # 构建界面
        self.create_widgets()
        self.refresh_tree()
        self.check_today_birthday()

    # 读取json文件
    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 []

    # 保存数据到json
    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):
        # 输入区域框架
        input_frame = tk.LabelFrame(self.root, text="新增生日信息", padx=10, pady=10)
        input_frame.pack(fill="x", padx=15, pady=8)

        # 姓名
        tk.Label(input_frame, text="姓名：").grid(row=0, column=0, sticky="w", pady=4)
        self.name_entry = tk.Entry(input_frame, width=15)
        self.name_entry.grid(row=0, column=1, padx=8)

        # 生日日期
        tk.Label(input_frame, text="生日(月-日)：").grid(row=0, column=2, sticky="w", pady=4)
        self.birth_entry = tk.Entry(input_frame, width=12)
        self.birth_entry.grid(row=0, column=3, padx=8)
        tk.Label(input_frame, text="格式示例：09-10").grid(row=0, column=4)

        # 备注
        tk.Label(input_frame, text="备注：").grid(row=1, column=0, sticky="w", pady=4)
        self.note_entry = tk.Entry(input_frame, width=40)
        self.note_entry.grid(row=1, column=1, columnspan=3, padx=8)

        # 按钮区域
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=5)
        tk.Button(btn_frame, text="添加", command=self.add_birthday, width=8).grid(row=0, column=0, padx=6)
        tk.Button(btn_frame, text="删除选中", command=self.del_birthday, width=8).grid(row=0, column=1, padx=6)
        tk.Button(btn_frame, text="刷新列表", command=self.refresh_tree, width=8).grid(row=0, column=2, padx=6)
        tk.Button(btn_frame, text="检查今日生日", command=self.check_today_birthday, width=10).grid(row=0, column=3, padx=6)

        # 表格展示区域
        table_frame = tk.LabelFrame(self.root, text="生日列表 / 距离生日天数", padx=5, pady=5)
        table_frame.pack(fill="both", expand=True, padx=15, pady=8)

        # 表格表头
        columns = ("name", "birth", "day_left", "note")
        self.tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=10)
        self.tree.heading("name", text="姓名")
        self.tree.heading("birth", text="生日(月-日)")
        self.tree.heading("day_left", text="剩余天数")
        self.tree.heading("note", text="备注")

        self.tree.column("name", width=120, anchor="center")
        self.tree.column("birth", width=100, anchor="center")
        self.tree.column("day_left", width=90, anchor="center")
        self.tree.column("note", width=260, anchor="center")

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

    # 计算距离下一次生日还有多少天
    def get_days_left(self, birth_str):
        now = datetime.now()
        month, day = map(int, birth_str.split("-"))
        try:
            this_year_birth = datetime(year=now.year, month=month, day=day)
        except ValueError:
            return "日期错误"
        if this_year_birth >= now:
            diff = this_year_birth - now
        else:
            next_year_birth = datetime(year=now.year + 1, month=month, day=day)
            diff = next_year_birth - now
        return diff.days

    # 添加生日
    def add_birthday(self):
        name = self.name_entry.get().strip()
        birth = self.birth_entry.get().strip()
        note = self.note_entry.get().strip()
        if not name or not birth:
            messagebox.showwarning("提示", "姓名和生日不能为空！")
            return
        # 校验日期格式
        try:
            m, d = map(int, birth.split("-"))
            datetime(2024, m, d)
        except:
            messagebox.showerror("错误", "生日格式错误，请使用 月-日 格式，例如 12-25")
            return
        self.birthdays.append({"name": name, "birth": birth, "note": note})
        self.save_data()
        # 清空输入框
        self.name_entry.delete(0, tk.END)
        self.birth_entry.delete(0, tk.END)
        self.note_entry.delete(0, tk.END)
        self.refresh_tree()
        messagebox.showinfo("成功", "生日信息添加完成")

    # 删除选中项
    def del_birthday(self):
        select_item = self.tree.selection()
        if not select_item:
            messagebox.showinfo("提示", "请先选中一条记录")
            return
        idx = self.tree.index(select_item[0])
        del self.birthdays[idx]
        self.save_data()
        self.refresh_tree()
        messagebox.showinfo("成功", "已删除该条生日记录")

    # 刷新表格数据
    def refresh_tree(self):
        # 清空原有数据
        for item in self.tree.get_children():
            self.tree.delete(item)
        # 重新插入
        for item in self.birthdays:
            days = self.get_days_left(item["birth"])
            self.tree.insert("", tk.END, values=(item["name"], item["birth"], days, item["note"]))

    # 检测今天有没有人生日
    def check_today_birthday(self):
        today = datetime.now().strftime("%m-%d")
        birthday_people = []
        for item in self.birthdays:
            if item["birth"] == today:
                birthday_people.append(item["name"])
        if birthday_people:
            names = "、".join(birthday_people)
            messagebox.showinfo("🎉 今日生日提醒", f"今天是【{names}】的生日，别忘了送上祝福！")
        else:
            messagebox.showinfo("提醒", "今天暂无人生日")

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