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

# 数据存储文件
DATA_FILE = "birthdays.json"

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

        # 加载已保存的生日数据
        self.birthdays = self.load_birthdays()

        # ========== 顶部：输入区域 ==========
        input_frame = ttk.LabelFrame(root, text="添加新生日")
        input_frame.pack(padx=10, pady=5, fill=tk.X)

        # 姓名
        ttk.Label(input_frame, text="姓名：").grid(row=0, column=0, padx=5, pady=5)
        self.name_entry = ttk.Entry(input_frame, width=15)
        self.name_entry.grid(row=0, column=1, padx=5, pady=5)

        # 日期（格式：YYYY-MM-DD）
        ttk.Label(input_frame, text="生日日期：").grid(row=0, column=2, padx=5, pady=5)
        self.date_entry = ttk.Entry(input_frame, width=15)
        self.date_entry.grid(row=0, column=3, padx=5, pady=5)
        ttk.Label(input_frame, text="格式：2025-10-01").grid(row=0, column=4, padx=5)

        # 按钮
        ttk.Button(input_frame, text="添加", command=self.add_birthday).grid(row=1, column=0, columnspan=2, pady=5)
        ttk.Button(input_frame, text="刷新", command=self.refresh_list).grid(row=1, column=2, columnspan=2, pady=5)

        # ========== 中间：生日列表 ==========
        list_frame = ttk.LabelFrame(root, text="生日列表")
        list_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)

        # 表格
        columns = ("name", "date", "days_left")
        self.tree = ttk.Treeview(list_frame, columns=columns, show="headings")
        self.tree.heading("name", text="姓名")
        self.tree.heading("date", text="生日")
        self.tree.heading("days_left", text="剩余天数")
        self.tree.column("name", width=120)
        self.tree.column("date", width=150)
        self.tree.column("days_left", width=120)

        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # ========== 底部：操作按钮 ==========
        btn_frame = ttk.Frame(root)
        btn_frame.pack(padx=10, pady=5)
        ttk.Button(btn_frame, text="删除选中", command=self.delete_birthday).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="清空所有", command=self.clear_all).pack(side=tk.LEFT, padx=5)

        # 初始化列表
        self.refresh_list()

    # 加载本地数据
    def load_birthdays(self):
        if os.path.exists(DATA_FILE):
            with open(DATA_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        return []

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

    # 计算距离生日还有多少天
    def get_days_left(self, birth_date_str):
        try:
            today = datetime.now()
            birth_date = datetime.strptime(birth_date_str, "%Y-%m-%d")
            # 替换为今年
            this_year_birth = birth_date.replace(year=today.year)
            
            if this_year_birth < today:
                # 今年已过，算明年
                this_year_birth = this_year_birth.replace(year=today.year + 1)
            
            delta = this_year_birth - today
            return delta.days + 1  # +1 包含今天
        except:
            return -1

    # 添加生日
    def add_birthday(self):
        name = self.name_entry.get().strip()
        date = self.date_entry.get().strip()

        if not name or not date:
            messagebox.showwarning("提示", "姓名和日期不能为空！")
            return

        # 校验日期格式
        try:
            datetime.strptime(date, "%Y-%m-%d")
        except ValueError:
            messagebox.showerror("错误", "日期格式错误！请使用：YYYY-MM-DD")
            return

        # 新增数据
        self.birthdays.append({"name": name, "date": date})
        self.save_birthdays()
        self.refresh_list()

        # 清空输入框
        self.name_entry.delete(0, tk.END)
        self.date_entry.delete(0, tk.END)
        messagebox.showinfo("成功", "生日添加完成！")

    # 刷新列表
    def refresh_list(self):
        # 清空原有内容
        for item in self.tree.get_children():
            self.tree.delete(item)

        today = datetime.now()
        # 插入数据
        for item in self.birthdays:
            name = item["name"]
            date = item["date"]
            days = self.get_days_left(date)

            # 显示文字
            if days == 0:
                days_text = "🎉 今天生日！"
            elif days == 1:
                days_text = "明天"
            else:
                days_text = f"{days} 天"

            # 当天生日标红
            if days == 0:
                self.tree.insert("", tk.END, values=(name, date, days_text), tags=("today",))
            else:
                self.tree.insert("", tk.END, values=(name, date, days_text))

        # 高亮样式
        self.tree.tag_configure("today", foreground="red", font=("", 10, "bold"))

    # 删除选中
    def delete_birthday(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择要删除的记录！")
            return

        # 获取选中项内容
        item = self.tree.item(selected[0])
        name = item["values"][0]

        # 确认删除
        if messagebox.askyesno("确认", f"确定要删除【{name}】的生日吗？"):
            # 从列表中移除
            self.birthdays = [b for b in self.birthdays if b["name"] != name]
            self.save_birthdays()
            self.refresh_list()

    # 清空所有
    def clear_all(self):
        if messagebox.askyesno("警告", "确定要清空所有生日记录吗？\n此操作不可恢复！"):
            self.birthdays = []
            self.save_birthdays()
            self.refresh_list()

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