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

# 数据文件名称
DATA_FILE = "birthday_data.json"
# 提醒天数：7天内过生日就高亮提示
REMIND_DAY = 7

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

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

        # 构建界面布局
        self.create_widgets()
        # 刷新表格数据
        self.refresh_table()

    # 读取json文件数据
    def load_data(self):
        try:
            with open(DATA_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        except (FileNotFoundError, json.JSONDecodeError):
            # 文件不存在/损坏返回空列表
            return []

    # 保存数据到json
    def save_data(self):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(self.birth_list, f, ensure_ascii=False, indent=2)

    # 界面组件创建
    def create_widgets(self):
        # 顶部输入区域框架
        frame_input = tk.Frame(self.root, padx=10, pady=10)
        frame_input.pack(fill="x")

        # 姓名
        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=5)

        # 生日 格式月-日
        tk.Label(frame_input, text="生日(月-日)：").grid(row=0, column=2, sticky="w", padx=(10,0))
        self.var_birth = tk.StringVar()
        tk.Entry(frame_input, textvariable=self.var_birth, width=10).grid(row=0, column=3, padx=5)

        # 备注
        tk.Label(frame_input, text="备注：").grid(row=0, column=4, sticky="w", padx=(10,0))
        self.var_note = tk.StringVar()
        tk.Entry(frame_input, textvariable=self.var_note, width=15).grid(row=0, column=5, padx=5)

        # 按钮区域
        frame_btn = tk.Frame(self.root, padx=10)
        frame_btn.pack(fill="x")
        tk.Button(frame_btn, text="添加生日", command=self.add_birthday, bg="#4CAF50", fg="white").pack(side="left", padx=3)
        tk.Button(frame_btn, text="删除选中", command=self.del_birthday, bg="#f44336", fg="white").pack(side="left", padx=3)
        tk.Button(frame_btn, text="刷新列表", command=self.refresh_table, bg="#2196F3", fg="white").pack(side="left", padx=3)
        tk.Button(frame_btn, text="检查今日提醒", command=self.check_remind).pack(side="left", padx=3)

        # 表格展示区域
        frame_table = tk.Frame(self.root, padx=10, pady=8)
        frame_table.pack(expand=True, fill="both")

        # 滚动条
        scroll_y = ttk.Scrollbar(frame_table)
        scroll_y.pack(side="right", fill="y")

        # 表格控件
        self.table = ttk.Treeview(
            frame_table,
            columns=("name", "birth", "note", "days"),
            show="headings",
            yscrollcommand=scroll_y.set
        )
        scroll_y.config(command=self.table.yview)

        # 表头设置
        self.table.heading("name", text="姓名")
        self.table.heading("birth", text="生日(月-日)")
        self.table.heading("note", text="备注")
        self.table.heading("days", text="距离生日天数")

        # 列宽
        self.table.column("name", width=120)
        self.table.column("birth", width=100)
        self.table.column("note", width=220)
        self.table.column("days", width=120)
        self.table.pack(expand=True, fill="both")

        # ==========修复点：tag_config → tag_configure==========
        self.table.tag_configure("warn", foreground="red")
        self.table.tag_configure("normal", foreground="black")

    # 计算距离下次生日还有多少天
    def get_days_left(self, birth_str):
        """birth_str: MM-DD"""
        now = datetime.now()
        this_year = now.year
        month, day = map(int, birth_str.split("-"))
        try:
            birth_date = datetime(this_year, month, day)
        except ValueError:
            return -999
        # 今年生日已过，计算明年
        if birth_date < now:
            birth_date = datetime(this_year + 1, month, day)
        delta = birth_date - now
        return delta.days

    # 添加生日
    def add_birthday(self):
        name = self.var_name.get().strip()
        birth = self.var_birth.get().strip()
        note = self.var_note.get().strip()
        if not name or not birth:
            messagebox.showwarning("提示", "姓名和生日不能为空！格式示例：08-15")
            return
        # 校验日期格式
        try:
            m, d = map(int, birth.split("-"))
            datetime(2000, m, d)
        except:
            messagebox.showerror("格式错误", "生日格式必须为：月-日 例：08-02")
            return
        # 存入列表
        self.birth_list.append({
            "name": name,
            "birth": birth,
            "note": note
        })
        self.save_data()
        # 清空输入框
        self.var_name.set("")
        self.var_birth.set("")
        self.var_note.set("")
        self.refresh_table()
        messagebox.showinfo("成功", "生日信息添加完成")

    # 删除选中条目
    def del_birthday(self):
        select_item = self.table.selection()
        if not select_item:
            messagebox.showinfo("提示", "请先选中一条记录")
            return
        index = self.table.index(select_item[0])
        del self.birth_list[index]
        self.save_data()
        self.refresh_table()
        messagebox.showinfo("完成", "已删除选中记录")

    # 刷新表格数据
    def refresh_table(self):
        # 清空原有表格
        for row in self.table.get_children():
            self.table.delete(row)
        # 遍历数据插入表格
        for item in self.birth_list:
            days = self.get_days_left(item["birth"])
            tag = "warn" if 0 <= days <= REMIND_DAY else "normal"
            self.table.insert(
                "", "end",
                values=(item["name"], item["birth"], item["note"], f"{days} 天"),
                tags=(tag,)
            )

    # 弹窗提醒最近过生日的人
    def check_remind(self):
        remind_list = []
        for item in self.birth_list:
            days = self.get_days_left(item["birth"])
            if 0 <= days <= REMIND_DAY:
                if days == 0:
                    remind_list.append(f"【今天】{item['name']} 过生日！备注：{item['note']}")
                else:
                    remind_list.append(f"{item['name']} 还有{days}天生日｜{item['birth']}｜备注：{item['note']}")
        if remind_list:
            msg = "\n".join(remind_list)
            messagebox.showwarning("生日提醒（7天内）", msg)
        else:
            messagebox.showinfo("提示", "最近7天暂无即将到来的生日")

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