import pygame
import json
import os
from datetime import datetime

# ===== 修改此处可以整体前后挪动日期 =====
TEST_TODAY = datetime(2026, 6, 13)  # 当前模拟：原日期+7天

# ========== 初始化配置 ==========
pygame.init()
WIDTH, HEIGHT = 600, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("生日提醒器")
clock = pygame.time.Clock()

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
BLUE = (100, 149, 237)
PINK = (255, 183, 197)
RED = (255, 69, 0)
GREEN = (34, 139, 34)

# 字体
font_small = pygame.font.SysFont("simhei", 20)
font_mid = pygame.font.SysFont("simhei", 24)
font_big = pygame.font.SysFont("simhei", 30)

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

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

def save_birthdays(data):
    """保存生日数据"""
    with open(DATA_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

def is_birthday_today(birth_str):
    """判断模拟当天是否过生日"""
    try:
        today = TEST_TODAY.strftime("%m-%d")
        b_month_day = birth_str[5:]
        return today == b_month_day
    except:
        return False

def get_days_remaining(birth_str):
    """计算距离下一次生日剩余天数（基于模拟日期）"""
    try:
        today = TEST_TODAY
        b_date = datetime.strptime(birth_str, "%Y-%m-%d")
        this_year_birth = datetime(today.year, b_date.month, b_date.day)
        
        if this_year_birth < today:
            next_birth = datetime(today.year + 1, b_date.month, b_date.day)
        else:
            next_birth = this_year_birth
            
        return (next_birth - today).days
    except:
        return 9999

# ========== 界面组件类 ==========
class InputBox:
    def __init__(self, x, y, w, h, text=""):
        self.rect = pygame.Rect(x, y, w, h)
        self.color = GRAY
        self.text = text
        self.txt_surface = font_small.render(text, True, BLACK)
        self.active = False

    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            self.active = self.rect.collidepoint(event.pos)
            self.color = BLUE if self.active else GRAY
        if event.type == pygame.KEYDOWN and self.active:
            if event.key == pygame.K_RETURN:
                pass
            elif event.key == pygame.K_BACKSPACE:
                self.text = self.text[:-1]
            else:
                self.text += event.unicode
            self.txt_surface = font_small.render(self.text, True, BLACK)

    def draw(self):
        pygame.draw.rect(screen, self.color, self.rect, 2)
        screen.blit(self.txt_surface, (self.rect.x+5, self.rect.y+8))

class Button:
    def __init__(self, x, y, w, h, text, color):
        self.rect = pygame.Rect(x, y, w, h)
        self.text = text
        self.color = color

    def draw(self):
        pygame.draw.rect(screen, self.color, self.rect)
        txt = font_small.render(self.text, True, WHITE)
        screen.blit(txt, (self.rect.x + 10, self.rect.y + 8))

    def is_clicked(self, pos):
        return self.rect.collidepoint(pos)

# ========== 主程序 ==========
def main():
    birthdays = load_birthdays()
    name_input = InputBox(80, 60, 200, 32)
    date_input = InputBox(300, 60, 200, 32)
    add_btn = Button(80, 100, 120, 35, "添加生日", GREEN)
    tip_today = ""

    running = True
    while running:
        screen.fill(WHITE)
        # 标题
        title = font_big.render("生日提醒器", True, PINK)
        screen.blit(title, (WIDTH//2 - title.get_width()//2, 10))

        # 标签
        screen.blit(font_small.render("姓名：", True, BLACK), (30, 65))
        screen.blit(font_small.render("日期：", True, BLACK), (220, 65))

        # 绘制组件
        name_input.draw()
        date_input.draw()
        add_btn.draw()

        # 今日提醒
        if tip_today:
            today_label = font_mid.render(f"今日寿星：{tip_today}", True, RED)
            screen.blit(today_label, (30, 150))

        # 列表标题
        pygame.draw.line(screen, GRAY, (30, 190), (570, 190), 2)
        list_title = font_small.render("即将过生日列表（按时间排序）", True, BLUE)
        screen.blit(list_title, (30, 200))

        # 排序生日列表
        sorted_list = sorted(birthdays, key=lambda x: get_days_remaining(x["date"]))

        # 绘制列表
        y = 230
        for item in sorted_list:
            name = item["name"]
            date = item["date"]
            days = get_days_remaining(date)
            
            if is_birthday_today(date):
                color = RED
                info = f"{name} | {date} | 今天过生日！"
            else:
                color = BLACK
                info = f"{name} | {date} | 还有 {days} 天"

            text = font_small.render(info, True, color)
            screen.blit(text, (30, y))
            y += 30

        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            name_input.handle_event(event)
            date_input.handle_event(event)

            if event.type == pygame.MOUSEBUTTONDOWN:
                if add_btn.is_clicked(event.pos):
                    name = name_input.text.strip()
                    date = date_input.text.strip()
                    if name and len(date) == 10 and date[4] == "-" and date[7] == "-":
                        birthdays.append({"name": name, "date": date})
                        save_birthdays(birthdays)
                        name_input.text = ""
                        date_input.text = ""
                        name_input.txt_surface = font_small.render("", True, BLACK)
                        date_input.txt_surface = font_small.render("", True, BLACK)

        # 检查今天生日
        today_names = []
        for item in birthdays:
            if is_birthday_today(item["date"]):
                today_names.append(item["name"])
        tip_today = "、".join(today_names) if today_names else ""

        pygame.display.flip()
        clock.tick(30)

    pygame.quit()

if __name__ == "__main__":
    main()