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


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

        # 数据文件
        self.data_file = "birthdays.json"
        self.birthdays = self.load_data()

        self.setup_ui()

        # 启动时检查
        self.root.after(500, self.check_today_birthdays)

    def setup_ui(self):
        # ===== 标题 =====
        title = tk.Label(
            self.root, text="🎂 生日提醒器",
            font=("Microsoft YaHei", 18, "bold"), fg="#e74c3c"
        )
        title.pack(pady=10)

        # ===== 输入区域 =====
        input_frame = tk.Frame(self.root)
        input_frame.pack(pady=5, padx=20, fill=tk.X)

        tk.Label(input_frame, text="姓名：", font=("Microsoft YaHei", 10)).grid(row=0, column=0, padx=5, pady=5, sticky="e")
        self.name_entry = tk.Entry(input_frame, font=("Microsoft YaHei", 10), width=15)
        self.name_entry.grid(row=0, column=1, padx=5, pady=5)

        tk.Label(input_frame, text="生日：", font=("Microsoft YaHei", 10)).grid(row=0, column=2, padx=5, pady=5, sticky="e")
        self.date_entry = tk.Entry(input_frame, font=("Microsoft YaHei", 10), width=15)
        self.date_entry.grid(row=0, column=3, padx=5, pady=5)
        self.date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))

        add_btn = tk.Button(
            input_frame, text="➕ 添加", width=10,
            font=("Microsoft YaHei", 9, "bold"),
            bg="#4CAF50", fg="white", activebackground="#45a049",
            command=self.add_birthday
        )
        add_btn.grid(row=0, column=4, padx=10, pady=5)

        # ===== 列表区域 =====
        list_frame = tk.Frame(self.root)
        list_frame.pack(pady=10, padx=20, fill=tk.BOTH, expand=True)

        # 表头
        columns = ("姓名", "生日", "距离生日")
        self.tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=12)

        for col in columns:
            self.tree.heading(col, text=col, anchor="center")
            self.tree.column(col, anchor="center", width=150)

        # 滚动条
        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(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 绑定双击编辑
        self.tree.bind("<Double-Button-1>", self.edit_birthday)

        # ===== 底部按钮 =====
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)

        tk.Button(
            btn_frame, text="🗑 删除选中", width=12,
            font=("Microsoft YaHei", 9),
            bg="#f44336", fg="white", activebackground="#da190b",
            command=self.delete_birthday
        ).pack(side=tk.LEFT, padx=5)

        tk.Button(
            btn_frame, text="🔄 刷新", width=12,
            font=("Microsoft YaHei", 9),
            bg="#2196F3", fg="white", activebackground="#1976D2",
            command=self.refresh_list
        ).pack(side=tk.LEFT, padx=5)

        tk.Button(
            btn_frame, text="🔍 检查今日", width=12,
            font=("Microsoft YaHei", 9),
            bg="#FF9800", fg="white", activebackground="#F57C00",
            command=self.check_today_birthdays
        ).pack(side=tk.LEFT, padx=5)

        # 底部提示
        self.status_label = tk.Label(
            self.root, text="", font=("Microsoft YaHei", 9), fg="#666"
        )
        self.status_label.pack(pady=3)

        # 加载列表
        self.refresh_list()

    # ===== 核心功能 =====
    def add_birthday(self):
        name = self.name_entry.get().strip()
        date_str = self.date_entry.get().strip()

        if not name:
            messagebox.showwarning("提示", "请输入姓名！")
            return

        try:
            datetime.strptime(date_str, "%Y-%m-%d")
        except ValueError:
            messagebox.showwarning("提示", "日期格式错误！\n请使用 YYYY-MM-DD 格式（如 2000-06-15）")
            return

        self.birthdays.append({"name": name, "date": date_str})
        self.save_data()
        self.refresh_list()

        self.name_entry.delete(0, tk.END)
        self.date_entry.delete(0, tk.END)
        self.date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))

        self.status_label.config(text=f"✅ 已添加：{name} 的生日")

    def edit_birthday(self, event):
        """双击编辑"""
        selection = self.tree.selection()
        if not selection:
            return

        item = selection[0]
        values = self.tree.item(item, "values")
        old_name, old_date, _ = values

        # 弹出编辑对话框
        dialog = tk.Toplevel(self.root)
        dialog.title("编辑生日")
        dialog.geometry("300x180")
        dialog.transient(self.root)
        dialog.grab_set()
        dialog.resizable(False, False)

        tk.Label(dialog, text="姓名：", font=("Microsoft YaHei", 10)).pack(pady=(20, 5))
        name_var = tk.StringVar(value=old_name)
        name_entry = tk.Entry(dialog, textvariable=name_var, font=("Microsoft YaHei", 10), width=20)
        name_entry.pack(pady=2)

        tk.Label(dialog, text="生日 (YYYY-MM-DD)：", font=("Microsoft YaHei", 10)).pack(pady=5)
        date_var = tk.StringVar(value=old_date)
        date_entry = tk.Entry(dialog, textvariable=date_var, font=("Microsoft YaHei", 10), width=20)
        date_entry.pack(pady=2)

        def save_edit():
            new_name = name_var.get().strip()
            new_date = date_var.get().strip()
            if not new_name:
                messagebox.showwarning("提示", "姓名不能为空！", parent=dialog)
                return
            try:
                datetime.strptime(new_date, "%Y-%m-%d")
            except ValueError:
                messagebox.showwarning("提示", "日期格式错误！", parent=dialog)
                return

            # 找到并更新
            for b in self.birthdays:
                if b["name"] == old_name and b["date"] == old_date:
                    b["name"] = new_name
                    b["date"] = new_date
                    break

            self.save_data()
            self.refresh_list()
            dialog.destroy()
            self.status_label.config(text=f"✅ 已更新：{new_name} 的生日")

        tk.Button(
            dialog, text="保存", width=12,
            bg="#4CAF50", fg="white", font=("Microsoft YaHei", 9),
            command=save_edit
        ).pack(pady=15)

        name_entry.focus_set()

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

        item = selection[0]
        values = self.tree.item(item, "values")
        name, date, _ = values

        if messagebox.askyesno("确认", f"确定删除 {name} 的生日记录吗？"):
            self.birthdays = [b for b in self.birthdays if not (b["name"] == name and b["date"] == date)]
            self.save_data()
            self.refresh_list()
            self.status_label.config(text=f"🗑 已删除：{name} 的生日")

    def refresh_list(self):
        """刷新列表显示"""
        # 清空
        for item in self.tree.get_children():
            self.tree.delete(item)

        # 排序：按月日排序（忽略年份）
        sorted_bdays = sorted(self.birthdays, key=lambda b: self._month_day_key(b["date"]))

        today = datetime.now()
        for b in sorted_bdays:
            name = b["name"]
            date_str = b["date"]
            days_left = self._days_until_birthday(date_str)

            if days_left == 0:
                display = "🎉 今天！"
            elif days_left == 1:
                display = "明天！"
            else:
                display = f"还有 {days_left} 天"

            self.tree.insert("", tk.END, values=(name, date_str, display))

    def check_today_birthdays(self):
        """检查今天是否有生日"""
        today_str = datetime.now().strftime("%m-%d")
        today_birthdays = []

        for b in self.birthdays:
            if b["date"][5:] == today_str:
                today_birthdays.append(b["name"])

        if today_birthdays:
            names = "、".join(today_birthdays)
            messagebox.showinfo(
                "🎂 生日提醒",
                f"今天有 {len(today_birthdays)} 人生日！\n\n🎉 {names} 🎂\n\n祝他们生日快乐！"
            )
            self.status_label.config(text=f"🎂 今天生日：{names}")
        else:
            self.status_label.config(text="今天没有生日提醒")

    # ===== 工具方法 =====
    def _days_until_birthday(self, date_str):
        """计算距离下次生日还有多少天"""
        today = datetime.now()
        bday = datetime.strptime(date_str, "%Y-%m-%d")

        # 今年的生日
        this_year_bday = bday.replace(year=today.year)
        if this_year_bday.date() < today.date():
            # 已过，算明年的
            this_year_bday = bday.replace(year=today.year + 1)

        return (this_year_bday.date() - today.date()).days

    def _month_day_key(self, date_str):
        """按月日排序的 key"""
        parts = date_str.split("-")
        return int(parts[1]) * 100 + int(parts[2])

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

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


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