import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import os
from datetime import datetime, timedelta
from typing import List, Dict, Tuple
import calendar
from PIL import Image, ImageTk
import time

class BirthdayPerson:
    """生日人员类"""
    def __init__(self, name: str, birthday: str, phone: str = "", 
                 email: str = "", relationship: str = "", notes: str = ""):
        self.name = name
        self.birthday = birthday
        self.phone = phone
        self.email = email
        self.relationship = relationship
        self.notes = notes
        self.last_notified = None
        self.reminder_days = 7  # 默认提前7天提醒
        
    def to_dict(self) -> Dict:
        """转换为字典"""
        return {
            'name': self.name,
            'birthday': self.birthday,
            'phone': self.phone,
            'email': self.email,
            'relationship': self.relationship,
            'notes': self.notes,
            'last_notified': self.last_notified,
            'reminder_days': self.reminder_days
        }
    
    @classmethod
    def from_dict(cls, data: Dict) -> 'BirthdayPerson':
        """从字典创建"""
        person = cls(
            name=data['name'],
            birthday=data['birthday'],
            phone=data.get('phone', ''),
            email=data.get('email', ''),
            relationship=data.get('relationship', ''),
            notes=data.get('notes', '')
        )
        person.last_notified = data.get('last_notified')
        person.reminder_days = data.get('reminder_days', 7)
        return person
    
    def get_next_birthday(self) -> datetime:
        """获取下一个生日日期"""
        today = datetime.now()
        
        try:
            # 解析生日日期
            if '-' in self.birthday:
                birth_date = datetime.strptime(self.birthday, '%Y-%m-%d')
            else:
                birth_date = datetime.strptime(self.birthday, '%m-%d')
                birth_date = birth_date.replace(year=today.year)
                
            # 如果今年的生日已经过了，计算明年的生日
            if birth_date < today:
                if '-' in self.birthday:
                    # 完整日期，增加一年
                    birth_date = birth_date.replace(year=today.year + 1)
                else:
                    # 只有月日，增加一年
                    birth_date = birth_date.replace(year=today.year + 1)
                    
            return birth_date
            
        except ValueError:
            return None
    
    def get_days_until_birthday(self) -> int:
        """计算距离生日的天数"""
        next_birthday = self.get_next_birthday()
        if not next_birthday:
            return None
            
        today = datetime.now().date()
        next_birthday_date = next_birthday.date()
        
        delta = next_birthday_date - today
        return delta.days
    
    def get_age(self) -> int:
        """计算年龄"""
        try:
            if '-' in self.birthday:
                birth_date = datetime.strptime(self.birthday, '%Y-%m-%d')
                today = datetime.now()
                age = today.year - birth_date.year
                
                # 如果今年生日还没过，减1岁
                if (today.month, today.day) < (birth_date.month, birth_date.day):
                    age -= 1
                    
                return age
            return None
        except:
            return None
    
    def should_notify(self) -> bool:
        """判断是否需要提醒"""
        days_left = self.get_days_until_birthday()
        if days_left is None:
            return False
            
        # 如果生日在今天或明天
        if days_left <= 1:
            return True
            
        # 如果设置了提前提醒
        if days_left <= self.reminder_days:
            return True
            
        return False
    
    def get_notification_message(self) -> str:
        """获取提醒消息"""
        days_left = self.get_days_until_birthday()
        age = self.get_age()
        
        if days_left == 0:
            message = f"🎂 今天生日！{self.name}"
            if age is not None:
                message += f" ({age}岁)"
        elif days_left == 1:
            message = f"🎁 明天生日！{self.name}"
            if age is not None:
                message += f" (即将{age+1}岁)"
        else:
            message = f"📅 {days_left}天后生日：{self.name}"
            if age is not None:
                message += f" (即将{age+1}岁)"
                
        return message

class BirthdayReminderApp:
    def __init__(self, root):
        self.root = root
        self.root.title("🎂 生日提醒器")
        
        # 窗口设置
        self.width = 1200
        self.height = 700
        self.root.geometry(f"{self.width}x{self.height}")
        
        # 数据
        self.people: List[BirthdayPerson] = []
        self.upcoming_birthdays: List[BirthdayPerson] = []
        
        # 加载数据
        self.load_data()
        
        # 创建界面
        self.create_widgets()
        
        # 设置自动检查提醒
        self.check_reminders()
        
    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = tk.Frame(self.root, bg='#f8f9fa')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 标题栏
        self.create_header(main_frame)
        
        # 主内容区
        self.create_main_content(main_frame)
        
        # 状态栏
        self.create_statusbar(main_frame)
        
    def create_header(self, parent):
        """创建标题栏"""
        header_frame = tk.Frame(parent, bg='#e74c3c', height=80)
        header_frame.pack(fill=tk.X, pady=(0, 10))
        header_frame.pack_propagate(False)
        
        # 标题
        title_label = tk.Label(header_frame, 
                              text="🎂 生日提醒器", 
                              font=("Microsoft YaHei", 28, "bold"),
                              fg="white", 
                              bg='#e74c3c')
        title_label.pack(pady=20)
        
    def create_main_content(self, parent):
        """创建主内容区"""
        # 左侧面板
        left_panel = tk.Frame(parent, width=300, bg='#f8f9fa')
        left_panel.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
        left_panel.pack_propagate(False)
        
        # 生日日历
        self.create_calendar_panel(left_panel)
        
        # 快速添加
        self.create_quick_add_panel(left_panel)
        
        # 统计信息
        self.create_stats_panel(left_panel)
        
        # 右侧主面板
        right_panel = tk.Frame(parent, bg='#f8f9fa')
        right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 标签页
        self.notebook = ttk.Notebook(right_panel)
        self.notebook.pack(fill=tk.BOTH, expand=True)
        
        # 创建标签页
        self.create_list_tab()
        self.create_upcoming_tab()
        self.create_calendar_tab()
        
    def create_calendar_panel(self, parent):
        """创建日历面板"""
        calendar_frame = tk.LabelFrame(parent, text="📅 本月生日", 
                                      font=("Microsoft YaHei", 12, "bold"),
                                      bg='white', fg="#2c3e50",
                                      padx=15, pady=15)
        calendar_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 月份和年份
        now = datetime.now()
        month_year = tk.Label(calendar_frame, 
                             text=f"{now.year}年 {now.month}月",
                             font=("Microsoft YaHei", 14, "bold"),
                             bg='white', fg="#e74c3c")
        month_year.pack()
        
        # 星期标题
        weekdays_frame = tk.Frame(calendar_frame, bg='white')
        weekdays_frame.pack(fill=tk.X, pady=(10, 5))
        
        weekdays = ["一", "二", "三", "四", "五", "六", "日"]
        for i, day in enumerate(weekdays):
            label = tk.Label(weekdays_frame, text=day, 
                           font=("Microsoft YaHei", 10, "bold"),
                           bg='white', fg="#7f8c8d", width=4)
            label.grid(row=0, column=i)
        
        # 日期网格
        self.calendar_grid_frame = tk.Frame(calendar_frame, bg='white')
        self.calendar_grid_frame.pack(fill=tk.X, pady=(5, 0))
        
        # 更新日历
        self.update_calendar()
        
    def update_calendar(self):
        """更新日历显示"""
        # 清除旧的日历
        for widget in self.calendar_grid_frame.winfo_children():
            widget.destroy()
        
        now = datetime.now()
        year = now.year
        month = now.month
        
        # 获取本月第一天是星期几
        first_day = datetime(year, month, 1)
        first_weekday = first_day.weekday()  # 0=周一, 6=周日
        
        # 获取本月天数
        days_in_month = calendar.monthrange(year, month)[1]
        
        # 获取本月有生日的人员
        month_birthdays = self.get_birthdays_in_month(month)
        
        row = 0
        col = first_weekday
        
        # 填充日期
        for day in range(1, days_in_month + 1):
            date_str = f"{year}-{month:02d}-{day:02d}"
            
            # 检查今天
            is_today = (day == now.day)
            
            # 检查是否有生日
            has_birthday = False
            birthday_names = []
            for person in month_birthdays:
                if person.birthday.endswith(f"{month:02d}-{day:02d}"):
                    has_birthday = True
                    birthday_names.append(person.name)
            
            # 创建日期按钮
            if is_today:
                bg_color = "#e74c3c"
                fg_color = "white"
            elif has_birthday:
                bg_color = "#f39c12"
                fg_color = "white"
            else:
                bg_color = "#ecf0f1"
                fg_color = "#2c3e50"
            
            day_frame = tk.Frame(self.calendar_grid_frame, bg=bg_color, 
                               height=30, width=30, relief=tk.RAISED, bd=1)
            day_frame.grid(row=row, column=col, padx=1, pady=1)
            day_frame.grid_propagate(False)
            
            day_label = tk.Label(day_frame, text=str(day), 
                               font=("Microsoft YaHei", 9, "bold" if is_today else "normal"),
                               bg=bg_color, fg=fg_color)
            day_label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
            
            # 如果有生日，显示提示
            if has_birthday:
                day_label.config(text=f"🎂\n{day}")
                tooltip_text = "\n".join(birthday_names)
                self.create_tooltip(day_frame, tooltip_text)
            
            col += 1
            if col >= 7:
                col = 0
                row += 1
    
    def get_birthdays_in_month(self, month: int) -> List[BirthdayPerson]:
        """获取指定月份的生日人员"""
        result = []
        for person in self.people:
            try:
                if '-' in person.birthday:
                    birth_month = int(person.birthday.split('-')[1])
                else:
                    birth_month = int(person.birthday.split('-')[0])
                
                if birth_month == month:
                    result.append(person)
            except:
                continue
        return result
    
    def create_tooltip(self, widget, text):
        """创建工具提示"""
        def enter(event):
            x, y, _, _ = widget.bbox("insert")
            x += widget.winfo_rootx() + 25
            y += widget.winfo_rooty() + 25
            
            self.tooltip = tk.Toplevel(widget)
            self.tooltip.wm_overrideredirect(True)
            self.tooltip.wm_geometry(f"+{x}+{y}")
            
            label = tk.Label(self.tooltip, text=text, 
                           justify='left', bg="#ffffe0", 
                           relief='solid', borderwidth=1,
                           font=("Microsoft YaHei", 9))
            label.pack()
        
        def leave(event):
            if hasattr(self, 'tooltip'):
                self.tooltip.destroy()
        
        widget.bind('<Enter>', enter)
        widget.bind('<Leave>', leave)
    
    def create_quick_add_panel(self, parent):
        """创建快速添加面板"""
        add_frame = tk.LabelFrame(parent, text="➕ 快速添加", 
                                 font=("Microsoft YaHei", 12, "bold"),
                                 bg='white', fg="#2c3e50",
                                 padx=15, pady=15)
        add_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 姓名
        tk.Label(add_frame, text="姓名:", 
                font=("Microsoft YaHei", 10),
                bg='white').grid(row=0, column=0, sticky=tk.W, pady=5)
        self.quick_name = tk.Entry(add_frame, width=20, font=("Microsoft YaHei", 10))
        self.quick_name.grid(row=0, column=1, pady=5, padx=(5, 0))
        
        # 生日
        tk.Label(add_frame, text="生日 (MM-DD):", 
                font=("Microsoft YaHei", 10),
                bg='white').grid(row=1, column=0, sticky=tk.W, pady=5)
        self.quick_birthday = tk.Entry(add_frame, width=20, font=("Microsoft YaHei", 10))
        self.quick_birthday.grid(row=1, column=1, pady=5, padx=(5, 0))
        
        # 关系
        tk.Label(add_frame, text="关系:", 
                font=("Microsoft YaHei", 10),
                bg='white').grid(row=2, column=0, sticky=tk.W, pady=5)
        self.quick_relationship = ttk.Combobox(add_frame, 
                                              values=["家人", "朋友", "同事", "同学", "其他"],
                                              width=18, font=("Microsoft YaHei", 10))
        self.quick_relationship.grid(row=2, column=1, pady=5, padx=(5, 0))
        
        # 添加按钮
        add_btn = tk.Button(add_frame, text="添加生日", 
                           command=self.quick_add_person,
                           font=("Microsoft YaHei", 10, "bold"),
                           bg="#2ecc71", fg="white",
                           relief=tk.RAISED, width=15)
        add_btn.grid(row=3, column=0, columnspan=2, pady=10)
    
    def create_stats_panel(self, parent):
        """创建统计面板"""
        stats_frame = tk.LabelFrame(parent, text="📊 统计", 
                                   font=("Microsoft YaHei", 12, "bold"),
                                   bg='white', fg="#2c3e50",
                                   padx=15, pady=15)
        stats_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 统计信息标签
        self.stats_labels = {}
        
        stats_data = [
            ("总人数:", "total_count"),
            ("本月生日:", "month_count"),
            ("即将生日:", "upcoming_count"),
            ("今天生日:", "today_count")
        ]
        
        for i, (label_text, key) in enumerate(stats_data):
            tk.Label(stats_frame, text=label_text, 
                    font=("Microsoft YaHei", 10),
                    bg='white').grid(row=i, column=0, sticky=tk.W, pady=3)
            
            value_label = tk.Label(stats_frame, text="0", 
                                  font=("Microsoft YaHei", 10, "bold"),
                                  bg='white', fg="#e74c3c")
            value_label.grid(row=i, column=1, sticky=tk.W, pady=3, padx=(10, 0))
            
            self.stats_labels[key] = value_label
        
        # 更新统计
        self.update_stats()
    
    def create_list_tab(self):
        """创建列表标签页"""
        list_frame = tk.Frame(self.notebook, bg='white')
        self.notebook.add(list_frame, text="👥 生日列表")
        
        # 工具栏
        toolbar = tk.Frame(list_frame, bg='#f8f9fa', height=40)
        toolbar.pack(fill=tk.X, pady=(0, 10))
        toolbar.pack_propagate(False)
        
        # 搜索框
        search_frame = tk.Frame(toolbar, bg='#f8f9fa')
        search_frame.pack(side=tk.LEFT, padx=10)
        
        tk.Label(search_frame, text="搜索:", 
                font=("Microsoft YaHei", 10),
                bg='#f8f9fa').pack(side=tk.LEFT)
        
        self.search_var = tk.StringVar()
        search_entry = tk.Entry(search_frame, textvariable=self.search_var,
                               width=20, font=("Microsoft YaHei", 10))
        search_entry.pack(side=tk.LEFT, padx=5)
        search_entry.bind('<KeyRelease>', self.filter_list)
        
        # 控制按钮
        btn_frame = tk.Frame(toolbar, bg='#f8f9fa')
        btn_frame.pack(side=tk.RIGHT, padx=10)
        
        buttons = [
            ("➕ 添加", self.add_person, "#2ecc71"),
            ("✏️ 编辑", self.edit_person, "#3498db"),
            ("🗑️ 删除", self.delete_person, "#e74c3c"),
            ("🔄 刷新", self.refresh_list, "#f39c12"),
            ("💾 导出", self.export_data, "#9b59b6")
        ]
        
        for text, command, color in buttons:
            btn = tk.Button(btn_frame, text=text, command=command,
                          font=("Microsoft YaHei", 9),
                          bg=color, fg="white",
                          relief=tk.FLAT, padx=10)
            btn.pack(side=tk.LEFT, padx=2)
        
        # 生日列表表格
        columns = ("姓名", "生日", "年龄", "距离天数", "关系", "电话", "邮箱")
        self.tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=20)
        
        # 设置列标题
        for col in columns:
            self.tree.heading(col, text=col)
            if col in ["姓名", "关系"]:
                self.tree.column(col, width=100)
            elif col in ["生日", "年龄", "距离天数"]:
                self.tree.column(col, width=80)
            else:
                self.tree.column(col, width=120)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定双击事件
        self.tree.bind('<Double-1>', self.on_item_double_click)
        
        # 更新列表
        self.update_birthday_list()
    
    def create_upcoming_tab(self):
        """创建即将生日标签页"""
        upcoming_frame = tk.Frame(self.notebook, bg='white')
        self.notebook.add(upcoming_frame, text="🔔 即将生日")
        
        # 工具栏
        toolbar = tk.Frame(upcoming_frame, bg='#f8f9fa', height=40)
        toolbar.pack(fill=tk.X, pady=(0, 10))
        toolbar.pack_propagate(False)
        
        # 提前提醒天数
        tk.Label(toolbar, text="提前提醒天数:", 
                font=("Microsoft YaHei", 10),
                bg='#f8f9fa').pack(side=tk.LEFT, padx=(10, 5))
        
        self.reminder_days_var = tk.StringVar(value="7")
        reminder_spin = ttk.Spinbox(toolbar, from_=1, to=30, 
                                   textvariable=self.reminder_days_var,
                                   width=5, font=("Microsoft YaHei", 10))
        reminder_spin.pack(side=tk.LEFT, padx=(0, 10))
        
        # 控制按钮
        btn_frame = tk.Frame(toolbar, bg='#f8f9fa')
        btn_frame.pack(side=tk.RIGHT, padx=10)
        
        tk.Button(btn_frame, text="🔔 测试提醒", 
                 command=self.test_notification,
                 font=("Microsoft YaHei", 9),
                 bg="#3498db", fg="white",
                 relief=tk.FLAT, padx=10).pack(side=tk.LEFT, padx=2)
        
        tk.Button(btn_frame, text="📧 发送提醒", 
                 command=self.send_notifications,
                 font=("Microsoft YaHei", 9),
                 bg="#2ecc71", fg="white",
                 relief=tk.FLAT, padx=10).pack(side=tk.LEFT, padx=2)
        
        # 即将生日列表
        self.upcoming_text = tk.Text(upcoming_frame, 
                                    font=("Microsoft YaHei", 12),
                                    bg='white', wrap=tk.WORD)
        
        scrollbar = ttk.Scrollbar(upcoming_frame, orient=tk.VERTICAL, 
                                 command=self.upcoming_text.yview)
        self.upcoming_text.configure(yscrollcommand=scrollbar.set)
        
        self.upcoming_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 更新即将生日列表
        self.update_upcoming_birthdays()
    
    def create_calendar_tab(self):
        """创建年度日历标签页"""
        calendar_frame = tk.Frame(self.notebook, bg='white')
        self.notebook.add(calendar_frame, text="📅 年度视图")
        
        # 年份选择
        year_frame = tk.Frame(calendar_frame, bg='#f8f9fa', height=40)
        year_frame.pack(fill=tk.X, pady=(0, 10))
        year_frame.pack_propagate(False)
        
        tk.Label(year_frame, text="年份:", 
                font=("Microsoft YaHei", 10),
                bg='#f8f9fa').pack(side=tk.LEFT, padx=(10, 5))
        
        current_year = datetime.now().year
        self.year_var = tk.StringVar(value=str(current_year))
        year_spin = ttk.Spinbox(year_frame, from_=1900, to=2100, 
                               textvariable=self.year_var,
                               width=8, font=("Microsoft YaHei", 10))
        year_spin.pack(side=tk.LEFT, padx=(0, 10))
        year_spin.bind('<<ComboboxSelected>>', self.update_year_calendar)
        
        # 年度日历框架
        self.year_calendar_frame = tk.Frame(calendar_frame, bg='white')
        self.year_calendar_frame.pack(fill=tk.BOTH, expand=True)
        
        # 更新年度日历
        self.update_year_calendar()
    
    def create_statusbar(self, parent):
        """创建状态栏"""
        status_frame = tk.Frame(parent, bg='#34495e', height=30)
        status_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=(10, 0))
        status_frame.pack_propagate(False)
        
        self.status_label = tk.Label(status_frame, 
                                    text=f"就绪 | 总人数: {len(self.people)} | 上次检查: {datetime.now().strftime('%H:%M:%S')}",
                                    font=("Microsoft YaHei", 9),
                                    fg="white", bg='#34495e',
                                    anchor=tk.W)
        self.status_label.pack(side=tk.LEFT, padx=10)
    
    def quick_add_person(self):
        """快速添加人员"""
        name = self.quick_name.get().strip()
        birthday = self.quick_birthday.get().strip()
        relationship = self.quick_relationship.get().strip()
        
        if not name or not birthday:
            messagebox.showwarning("警告", "请填写姓名和生日！")
            return
        
        # 验证生日格式
        if not self.validate_birthday(birthday):
            messagebox.showwarning("警告", "生日格式错误！请使用 MM-DD 格式")
            return
        
        # 创建人员对象
        person = BirthdayPerson(name, birthday, relationship=relationship)
        self.people.append(person)
        
        # 保存数据
        self.save_data()
        
        # 更新界面
        self.update_birthday_list()
        self.update_calendar()
        self.update_stats()
        self.update_upcoming_birthdays()
        
        # 清空输入框
        self.quick_name.delete(0, tk.END)
        self.quick_birthday.delete(0, tk.END)
        
        messagebox.showinfo("成功", f"已添加 {name} 的生日")
    
    def add_person(self):
        """添加人员（完整信息）"""
        dialog = AddPersonDialog(self.root)
        if dialog.result:
            person = BirthdayPerson(
                name=dialog.result['name'],
                birthday=dialog.result['birthday'],
                phone=dialog.result['phone'],
                email=dialog.result['email'],
                relationship=dialog.result['relationship'],
                notes=dialog.result['notes']
            )
            self.people.append(person)
            self.save_data()
            self.update_birthday_list()
            self.update_calendar()
            self.update_stats()
            self.update_upcoming_birthdays()
    
    def edit_person(self):
        """编辑人员信息"""
        selection = self.tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择要编辑的人员！")
            return
        
        item = selection[0]
        values = self.tree.item(item, 'values')
        
        # 找到对应的人员
        for person in self.people:
            if person.name == values[0] and person.birthday == values[1]:
                dialog = EditPersonDialog(self.root, person)
                if dialog.result:
                    # 更新人员信息
                    person.name = dialog.result['name']
                    person.birthday = dialog.result['birthday']
                    person.phone = dialog.result['phone']
                    person.email = dialog.result['email']
                    person.relationship = dialog.result['relationship']
                    person.notes = dialog.result['notes']
                    
                    self.save_data()
                    self.update_birthday_list()
                    self.update_calendar()
                    self.update_stats()
                    self.update_upcoming_birthdays()
                break
    
    def delete_person(self):
        """删除人员"""
        selection = self.tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请先选择要删除的人员！")
            return
        
        item = selection[0]
        values = self.tree.item(item, 'values')
        
        if messagebox.askyesno("确认", f"确定要删除 {values[0]} 的生日记录吗？"):
            # 找到并删除人员
            for i, person in enumerate(self.people):
                if person.name == values[0] and person.birthday == values[1]:
                    del self.people[i]
                    break
            
            self.save_data()
            self.update_birthday_list()
            self.update_calendar()
            self.update_stats()
            self.update_upcoming_birthdays()
    
    def refresh_list(self):
        """刷新列表"""
        self.update_birthday_list()
        self.update_calendar()
        self.update_stats()
        self.update_upcoming_birthdays()
        self.status_label.config(text=f"已刷新 | 总人数: {len(self.people)} | 时间: {datetime.now().strftime('%H:%M:%S')}")
    
    def filter_list(self, event=None):
        """过滤列表"""
        search_text = self.search_var.get().lower()
        
        # 清空当前列表
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 重新添加匹配的人员
        for person in self.people:
            if (search_text in person.name.lower() or 
                search_text in person.birthday.lower() or
                search_text in person.relationship.lower() or
                search_text in person.phone.lower() or
                search_text in person.email.lower()):
                
                self.add_person_to_tree(person)
    
    def update_birthday_list(self):
        """更新生日列表"""
        # 清空当前列表
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 按距离生日天数排序
        sorted_people = sorted(self.people, key=lambda p: p.get_days_until_birthday() or 9999)
        
        # 添加人员到列表
        for person in sorted_people:
            self.add_person_to_tree(person)
    
    def add_person_to_tree(self, person):
        """添加人员到树形列表"""
        days_left = person.get_days_until_birthday()
        age = person.get_age()
        
        if days_left is not None and days_left <= 7:
            tag = 'urgent'
        elif days_left is not None and days_left <= 30:
            tag = 'warning'
        else:
            tag = 'normal'
        
        values = (
            person.name,
            person.birthday,
            str(age) if age is not None else "未知",
            str(days_left) if days_left is not None else "未知",
            person.relationship,
            person.phone,
            person.email
        )
        
        item = self.tree.insert("", tk.END, values=values, tags=(tag,))
        
        # 设置标签颜色
        if tag == 'urgent':
            self.tree.tag_configure(tag, background='#ffcccc')
        elif tag == 'warning':
            self.tree.tag_configure(tag, background='#ffffcc')
    
    def update_upcoming_birthdays(self):
        """更新即将生日列表"""
        self.upcoming_birthdays = []
        
        for person in self.people:
            if person.should_notify():
                self.upcoming_birthdays.append(person)
        
        # 按距离生日天数排序
        self.upcoming_birthdays.sort(key=lambda p: p.get_days_until_birthday() or 9999)
        
        # 更新文本显示
        self.upcoming_text.delete(1.0, tk.END)
        
        if not self.upcoming_birthdays:
            self.upcoming_text.insert(tk.END, "🎉 暂时没有即将到来的生日！\n\n")
        else:
            for person in self.upcoming_birthdays:
                days_left = person.get_days_until_birthday()
                message = person.get_notification_message()
                
                # 设置不同天数的格式
                if days_left == 0:
                    self.upcoming_text.insert(tk.END, f"🔥 {message}\n", 'urgent')
                elif days_left == 1:
                    self.upcoming_text.insert(tk.END, f"⚠️  {message}\n", 'warning')
                elif days_left <= 7:
                    self.upcoming_text.insert(tk.END, f"📌 {message}\n", 'important')
                else:
                    self.upcoming_text.insert(tk.END, f"📅 {message}\n")
                
                # 添加详细信息
                self.upcoming_text.insert(tk.END, f"   关系: {person.relationship}\n")
                if person.phone:
                    self.upcoming_text.insert(tk.END, f"   电话: {person.phone}\n")
                if person.email:
                    self.upcoming_text.insert(tk.END, f"   邮箱: {person.email}\n")
                if person.notes:
                    self.upcoming_text.insert(tk.END, f"   备注: {person.notes}\n")
                self.upcoming_text.insert(tk.END, "-"*40 + "\n")
        
        # 配置标签
        self.upcoming_text.tag_config('urgent', foreground='#e74c3c', font=('Microsoft YaHei', 12, 'bold'))
        self.upcoming_text.tag_config('warning', foreground='#f39c12', font=('Microsoft YaHei', 12, 'bold'))
        self.upcoming_text.tag_config('important', foreground='#3498db', font=('Microsoft YaHei', 12))
    
    def update_year_calendar(self, event=None):
        """更新年度日历"""
        # 清除旧的日历
        for widget in self.year_calendar_frame.winfo_children():
            widget.destroy()
        
        try:
            year = int(self.year_var.get())
        except:
            year = datetime.now().year
        
        # 创建12个月的日历
        for month in range(1, 13):
            month_frame = tk.LabelFrame(self.year_calendar_frame, 
                                       text=f"{year}年 {month}月",
                                       font=("Microsoft YaHei", 10, "bold"),
                                       bg='white', fg="#2c3e50")
            month_frame.grid(row=(month-1)//3, column=(month-1)%3, 
                            padx=5, pady=5, sticky=tk.NSEW)
            
            # 获取本月生日人员
            month_birthdays = self.get_birthdays_in_month(month)
            
            # 星期标题
            weekdays_frame = tk.Frame(month_frame, bg='white')
            weekdays_frame.pack(fill=tk.X, pady=(5, 2))
            
            weekdays = ["一", "二", "三", "四", "五", "六", "日"]
            for i, day in enumerate(weekdays):
                label = tk.Label(weekdays_frame, text=day, 
                               font=("Microsoft YaHei", 8),
                               bg='white', fg="#7f8c8d", width=2)
                label.grid(row=0, column=i)
            
            # 日期网格
            grid_frame = tk.Frame(month_frame, bg='white')
            grid_frame.pack(fill=tk.X, pady=(2, 5))
            
            # 获取本月第一天是星期几
            first_day = datetime(year, month, 1)
            first_weekday = first_day.weekday()
            
            # 获取本月天数
            days_in_month = calendar.monthrange(year, month)[1]
            
            row = 0
            col = first_weekday
            
            for day in range(1, days_in_month + 1):
                date_str = f"{year}-{month:02d}-{day:02d}"
                
                # 检查今天
                now = datetime.now()
                is_today = (year == now.year and month == now.month and day == now.day)
                
                # 检查是否有生日
                has_birthday = False
                birthday_names = []
                for person in month_birthdays:
                    if person.birthday.endswith(f"{month:02d}-{day:02d}"):
                        has_birthday = True
                        birthday_names.append(person.name[:2])  # 只显示前两个字符
                
                # 创建日期标签
                if is_today:
                    bg_color = "#e74c3c"
                    fg_color = "white"
                elif has_birthday:
                    bg_color = "#f39c12"
                    fg_color = "white"
                else:
                    bg_color = "#f8f9fa"
                    fg_color = "#2c3e50"
                
                day_label = tk.Label(grid_frame, text=str(day), 
                                    font=("Microsoft YaHei", 8, "bold" if is_today else "normal"),
                                    bg=bg_color, fg=fg_color, width=2, height=1)
                day_label.grid(row=row, column=col, padx=1, pady=1)
                
                # 如果有生日，显示图标
                if has_birthday:
                    day_label.config(text=f"🎂\n{day}")
                
                col += 1
                if col >= 7:
                    col = 0
                    row += 1
        
        # 配置网格权重
        for i in range(4):
            self.year_calendar_frame.rowconfigure(i, weight=1)
        for i in range(3):
            self.year_calendar_frame.columnconfigure(i, weight=1)
    
    def update_stats(self):
        """更新统计信息"""
        now = datetime.now()
        month = now.month
        
        # 计算各种统计
        total_count = len(self.people)
        month_count = len(self.get_birthdays_in_month(month))
        
        today_count = 0
        upcoming_count = 0
        
        for person in self.people:
            days_left = person.get_days_until_birthday()
            if days_left == 0:
                today_count += 1
            elif days_left is not None and days_left <= 30:
                upcoming_count += 1
        
        # 更新标签
        self.stats_labels['total_count'].config(text=str(total_count))
        self.stats_labels['month_count'].config(text=str(month_count))
        self.stats_labels['today_count'].config(text=str(today_count))
        self.stats_labels['upcoming_count'].config(text=str(upcoming_count))
    
    def check_reminders(self):
        """检查提醒"""
        # 检查是否需要提醒
        for person in self.people:
            if person.should_notify():
                # 避免重复提醒
                if person.last_notified != datetime.now().strftime('%Y-%m-%d'):
                    self.show_notification(person)
                    person.last_notified = datetime.now().strftime('%Y-%m-%d')
        
        # 保存更新
        self.save_data()
        
        # 更新界面
        self.update_upcoming_birthdays()
        self.update_stats()
        
        # 每分钟检查一次
        self.root.after(60000, self.check_reminders)
    
    def show_notification(self, person):
        """显示提醒"""
        message = person.get_notification_message()
        
        # 创建提醒窗口
        notification = tk.Toplevel(self.root)
        notification.title("生日提醒")
        notification.geometry("400x200")
        notification.configure(bg='#2c3e50')
        
        # 居中显示
        x = self.root.winfo_x() + (self.root.winfo_width() - 400) // 2
        y = self.root.winfo_y() + (self.root.winfo_height() - 200) // 2
        notification.geometry(f"400x200+{x}+{y}")
        
        # 内容
        tk.Label(notification, text="🎂 生日提醒 🎂", 
                font=("Microsoft YaHei", 20, "bold"),
                bg='#2c3e50', fg='white').pack(pady=20)
        
        tk.Label(notification, text=message, 
                font=("Microsoft YaHei", 16),
                bg='#2c3e50', fg='#f39c12').pack(pady=10)
        
        tk.Label(notification, text=f"关系: {person.relationship}", 
                font=("Microsoft YaHei", 12),
                bg='#2c3e50', fg='white').pack(pady=5)
        
        if person.phone:
            tk.Label(notification, text=f"电话: {person.phone}", 
                    font=("Microsoft YaHei", 12),
                    bg='#2c3e50', fg='white').pack(pady=5)
        
        # 自动关闭
        notification.after(10000, notification.destroy)
    
    def test_notification(self):
        """测试提醒"""
        if not self.people:
            messagebox.showinfo("提示", "暂无生日记录")
            return
        
        # 使用第一个人进行测试
        person = self.people[0]
        self.show_notification(person)
    
    def send_notifications(self):
        """发送提醒"""
        if not self.upcoming_birthdays:
            messagebox.showinfo("提示", "当前没有需要提醒的生日")
            return
        
        # 汇总提醒
        messages = []
        for person in self.upcoming_birthdays:
            messages.append(person.get_notification_message())
        
        # 显示汇总
        summary = "\n".join(messages)
        messagebox.showinfo("生日提醒汇总", f"需要提醒的生日：\n\n{summary}")
    
    def export_data(self):
        """导出数据"""
        from tkinter import filedialog
        
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                data = [person.to_dict() for person in self.people]
                with open(file_path, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
                messagebox.showinfo("成功", f"数据已导出到：{file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"导出失败：{str(e)}")
    
    def on_item_double_click(self, event):
        """双击项目"""
        item = self.tree.identify_row(event.y)
        if item:
            self.edit_person()
    
    def validate_birthday(self, birthday: str) -> bool:
        """验证生日格式"""
        try:
            if '-' in birthday and len(birthday.split('-')) == 3:
                # YYYY-MM-DD 格式
                datetime.strptime(birthday, '%Y-%m-%d')
            elif '-' in birthday and len(birthday.split('-')) == 2:
                # MM-DD 格式
                datetime.strptime(birthday, '%m-%d')
            else:
                return False
            return True
        except ValueError:
            return False
    
    def load_data(self):
        """加载数据"""
        try:
            if os.path.exists("birthdays.json"):
                with open("birthdays.json", 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    self.people = [BirthdayPerson.from_dict(item) for item in data]
            else:
                # 添加示例数据
                self.people = [
                    BirthdayPerson("小明", "1990-05-15", "13800138000", 
                                  "xiaoming@example.com", "朋友", "喜欢打篮球"),
                    BirthdayPerson("小红", "08-20", "", "xiaohong@example.com", 
                                  "同事", "注意是农历生日"),
                    BirthdayPerson("张三", "12-25", "13900139000", "", 
                                  "家人", "圣诞节生日"),
                    BirthdayPerson("李四", "1995-03-08", "", "", 
                                  "同学", ""),
                ]
        except:
            # 添加示例数据
            self.people = [
                BirthdayPerson("小明", "1990-05-15", "13800138000", 
                              "xiaoming@example.com", "朋友", "喜欢打篮球"),
                BirthdayPerson("小红", "08-20", "", "xiaohong@example.com", 
                              "同事", "注意是农历生日"),
                BirthdayPerson("张三", "12-25", "13900139000", "", 
                              "家人", "圣诞节生日"),
                BirthdayPerson("李四", "1995-03-08", "", "", 
                              "同学", ""),
            ]
    
    def save_data(self):
        """保存数据"""
        try:
            data = [person.to_dict() for person in self.people]
            with open("birthdays.json", 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存数据失败：{e}")

class AddPersonDialog:
    """添加人员对话框"""
    def __init__(self, parent):
        self.parent = parent
        self.result = None
        
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("添加生日")
        self.dialog.geometry("400x500")
        self.dialog.transient(parent)
        self.dialog.grab_set()
        
        # 居中显示
        x = parent.winfo_x() + (parent.winfo_width() - 400) // 2
        y = parent.winfo_y() + (parent.winfo_height() - 500) // 2
        self.dialog.geometry(f"400x500+{x}+{y}")
        
        # 创建表单
        self.create_form()
    
    def create_form(self):
        """创建表单"""
        tk.Label(self.dialog, text="添加生日信息", 
                font=("Microsoft YaHei", 16, "bold")).pack(pady=20)
        
        # 姓名
        tk.Label(self.dialog, text="姓名*:", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.name_var = tk.StringVar()
        tk.Entry(self.dialog, textvariable=self.name_var, 
                font=("Microsoft YaHei", 12), width=30).pack(padx=30, pady=(0, 10))
        
        # 生日
        tk.Label(self.dialog, text="生日* (YYYY-MM-DD 或 MM-DD):", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.birthday_var = tk.StringVar()
        tk.Entry(self.dialog, textvariable=self.birthday_var, 
                font=("Microsoft YaHei", 12), width=30).pack(padx=30, pady=(0, 10))
        
        # 电话
        tk.Label(self.dialog, text="电话:", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.phone_var = tk.StringVar()
        tk.Entry(self.dialog, textvariable=self.phone_var, 
                font=("Microsoft YaHei", 12), width=30).pack(padx=30, pady=(0, 10))
        
        # 邮箱
        tk.Label(self.dialog, text="邮箱:", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.email_var = tk.StringVar()
        tk.Entry(self.dialog, textvariable=self.email_var, 
                font=("Microsoft YaHei", 12), width=30).pack(padx=30, pady=(0, 10))
        
        # 关系
        tk.Label(self.dialog, text="关系:", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.relationship_var = tk.StringVar()
        ttk.Combobox(self.dialog, textvariable=self.relationship_var,
                    values=["家人", "朋友", "同事", "同学", "其他"],
                    font=("Microsoft YaHei", 12), width=28).pack(padx=30, pady=(0, 10))
        
        # 备注
        tk.Label(self.dialog, text="备注:", 
                font=("Microsoft YaHei", 12)).pack(anchor=tk.W, padx=30, pady=5)
        self.notes_text = tk.Text(self.dialog, height=4, width=30,
                                 font=("Microsoft YaHei", 12))
        self.notes_text.pack(padx=30, pady=(0, 20))
        
        # 按钮
        btn_frame = tk.Frame(self.dialog)
        btn_frame.pack(pady=10)
        
        tk.Button(btn_frame, text="确定", command=self.save,
                 font=("Microsoft YaHei", 12), bg="#2ecc71", fg="white",
                 width=10).pack(side=tk.LEFT, padx=10)
        
        tk.Button(btn_frame, text="取消", command=self.dialog.destroy,
                 font=("Microsoft YaHei", 12), bg="#e74c3c", fg="white",
                 width=10).pack(side=tk.LEFT, padx=10)
    
    def save(self):
        """保存"""
        name = self.name_var.get().strip()
        birthday = self.birthday_var.get().strip()
        
        if not name or not birthday:
            messagebox.showwarning("警告", "请填写姓名和生日！")
            return
        
        # 验证生日格式
        try:
            if '-' in birthday and len(birthday.split('-')) == 3:
                datetime.strptime(birthday, '%Y-%m-%d')
            elif '-' in birthday and len(birthday.split('-')) == 2:
                datetime.strptime(birthday, '%m-%d')
            else:
                raise ValueError
        except ValueError:
            messagebox.showwarning("警告", "生日格式错误！请使用 YYYY-MM-DD 或 MM-DD 格式")
            return
        
        self.result = {
            'name': name,
            'birthday': birthday,
            'phone': self.phone_var.get().strip(),
            'email': self.email_var.get().strip(),
            'relationship': self.relationship_var.get().strip(),
            'notes': self.notes_text.get(1.0, tk.END).strip()
        }
        
        self.dialog.destroy()

class EditPersonDialog(AddPersonDialog):
    """编辑人员对话框"""
    def __init__(self, parent, person):
        self.person = person
        super().__init__(parent)
        self.dialog.title("编辑生日")
        self.load_person_data()
    
    def load_person_data(self):
        """加载人员数据"""
        self.name_var.set(self.person.name)
        self.birthday_var.set(self.person.birthday)
        self.phone_var.set(self.person.phone)
        self.email_var.set(self.person.email)
        self.relationship_var.set(self.person.relationship)
        self.notes_text.delete(1.0, tk.END)
        self.notes_text.insert(1.0, self.person.notes)

def main():
    """主函数"""
    root = tk.Tk()
    
    # 设置窗口位置
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    width = 1200
    height = 700
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f"{width}x{height}+{x}+{y}")
    
    app = BirthdayReminderApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()