import pygame
import sys
import json
import os
from datetime import datetime, date, timedelta
from calendar import monthcalendar, month_name, day_name

# 初始化Pygame
pygame.init()

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
DARK_GRAY = (100, 100, 100)
LIGHT_BLUE = (173, 216, 230)
BLUE = (70, 130, 180)
RED = (255, 99, 71)
GREEN = (144, 238, 144)
ORANGE = (255, 165, 0)
LIGHT_YELLOW = (255, 253, 208)

# 窗口设置
WIDTH, HEIGHT = 950, 680
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("日历提醒与计划表")
clock = pygame.time.Clock()

# 尝试加载支持中文的字体
def get_chinese_font(size):
    """获取支持中文的字体"""
    # Windows系统常见中文字体
    font_paths = [
        "C:/Windows/Fonts/simhei.ttf",      # 黑体
        "C:/Windows/Fonts/simsun.ttc",       # 宋体
        "C:/Windows/Fonts/msyh.ttc",         # 微软雅黑
        "C:/Windows/Fonts/msyhbd.ttc",       # 微软雅黑粗体
        "/System/Library/Fonts/PingFang.ttc", # macOS
        "/System/Library/Fonts/STHeiti Light.ttc",
        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", # Linux
        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
    ]
    
    for path in font_paths:
        if os.path.exists(path):
            try:
                return pygame.font.Font(path, size)
            except:
                continue
    
    # 如果找不到系统字体，尝试使用默认字体
    try:
        return pygame.font.SysFont("simhei", size)
    except:
        pass
    
    try:
        return pygame.font.SysFont("microsoftyaheimicrosoftyaheyi", size)
    except:
        pass
    
    # 最后回退到默认字体
    return pygame.font.Font(None, size)

# 创建不同大小的字体
font_large = get_chinese_font(48)
font_medium = get_chinese_font(32)
font_small = get_chinese_font(24)

# 数据文件路径
DATA_FILE = "calendar_data.json"

class CalendarApp:
    def __init__(self):
        self.current_date = date.today()
        self.selected_date = None
        self.show_input = False
        self.input_text = ""
        self.plans = self.load_data()
        self.dragging = False
        self.scroll_offset = 0
        
    def load_data(self):
        """加载保存的计划数据"""
        if os.path.exists(DATA_FILE):
            try:
                with open(DATA_FILE, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    return data
            except:
                return {}
        return {}
    
    def save_data(self):
        """保存计划数据到文件"""
        with open(DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(self.plans, f, ensure_ascii=False, indent=2)
    
    def add_plan(self, date_str, plan_text):
        """为指定日期添加计划"""
        if date_str not in self.plans:
            self.plans[date_str] = []
        self.plans[date_str].append({
            "text": plan_text,
            "time": datetime.now().strftime("%H:%M"),
            "completed": False
        })
        self.save_data()
    
    def toggle_complete(self, date_str, index):
        """切换计划的完成状态"""
        if date_str in self.plans and 0 <= index < len(self.plans[date_str]):
            self.plans[date_str][index]["completed"] = not self.plans[date_str][index]["completed"]
            self.save_data()
    
    def delete_plan(self, date_str, index):
        """删除计划"""
        if date_str in self.plans and 0 <= index < len(self.plans[date_str]):
            del self.plans[date_str][index]
            if len(self.plans[date_str]) == 0:
                del self.plans[date_str]
            self.save_data()
    
    def draw_calendar(self):
        """绘制日历网格"""
        # 标题区域
        title_text = f"{self.current_date.year}年 {month_name[self.current_date.month]}"
        title_surf = font_large.render(title_text, True, BLACK)
        screen.blit(title_surf, (30, 20))
        
        # 导航按钮
        prev_rect = pygame.Rect(280, 25, 88, 38)
        next_rect = pygame.Rect(380, 25, 68, 38)
        today_rect = pygame.Rect(460, 27, 72, 32)
        
        pygame.draw.rect(screen, LIGHT_BLUE, prev_rect, border_radius=5)
        pygame.draw.rect(screen, LIGHT_BLUE, next_rect, border_radius=5)
        pygame.draw.rect(screen, GREEN, today_rect, border_radius=3)
        
        prev_text = font_small.render("< 上月", True, BLACK)
        next_text = font_small.render("下月 >", True, BLACK)
        today_text = font_small.render("今天", True, WHITE)
        
        screen.blit(prev_text, (292, 31))
        screen.blit(next_text, (390, 33))
        screen.blit(today_text, (470, 32))
        
        # 星期标题
        days = ["一", "二", "三", "四", "五", "六", "日"]
        for i, day in enumerate(days):
            text = font_small.render(day, True, DARK_GRAY if i < 5 else RED)
            screen.blit(text, (50 + i * 87, 77))
        
        # 绘制日期格子
        cal = monthcalendar(self.current_date.year, self.current_date.month)
        cell_size = 84
        start_y = 107
        
        for row_idx, week in enumerate(cal):
            for col_idx, day in enumerate(week):
                if day != 0:
                    x = 43 + col_idx * cell_size
                    y = start_y + row_idx * cell_size
                    
                    # 判断是否是周末
                    is_weekend = col_idx >= 5
                    
                    # 判断是否是今天
                    is_today = (day == self.current_date.day and 
                               self.current_date.month == date.today().month and
                               self.current_date.year == date.today().year)
                    
                    # 判断是否被选中
                    is_selected = (self.selected_date and 
                                  day == self.selected_date.day and
                                  self.current_date.month == self.selected_date.month and
                                  self.current_date.year == self.selected_date.year)
                    
                    # 绘制背景
                    if is_selected:
                        pygame.draw.rect(screen, BLUE, (x, y, cell_size-3, cell_size-3), border_radius=5)
                        text_color = WHITE
                    elif is_today:
                        pygame.draw.rect(screen, LIGHT_YELLOW, (x, y, cell_size-3, cell_size-3), border_radius=5)
                        text_color = RED
                    else:
                        pygame.draw.rect(screen, GRAY if is_weekend else WHITE, 
                                       (x, y, cell_size-3, cell_size-3), border_radius=3)
                        text_color = RED if is_weekend else BLACK
                    
                    # 绘制日期数字
                    day_text = font_medium.render(str(day), True, text_color)
                    screen.blit(day_text, (x + 9, y + 4))
                    
                    # 如果有计划，显示小点
                    date_key = f"{self.current_date.year}-{self.current_date.month:02d}-{day:02d}"
                    if date_key in self.plans and len(self.plans[date_key]) > 0:
                        count = len(self.plans[date_key])
                        count_text = font_small.render(f"● {count}", True, ORANGE)
                        screen.blit(count_text, (x + 38, y + 54))
    
    def draw_plans_panel(self):
        """绘制右侧计划面板"""
        panel_x = 640
        panel_width = WIDTH - panel_x - 15
        
        # 面板背景
        pygame.draw.rect(screen, (245, 245, 248), (panel_x, 10, panel_width, HEIGHT-20), border_radius=10)
        pygame.draw.rect(screen, DARK_GRAY, (panel_x, 10, panel_width, HEIGHT-20), 2, border_radius=10)
        
        # 标题
        if self.selected_date:
            title = f"{self.selected_date.month}月{self.selected_date.day}日 计划"
        else:
            title = "请选择日期"
        title_surf = font_medium.render(title, True, BLACK)
        screen.blit(title_surf, (panel_x + 15, 20))
        
        if self.selected_date:
            date_key = f"{self.selected_date.year}-{self.selected_date.month:02d}-{self.selected_date.day:02d}"
            plans = self.plans.get(date_key, [])
            
            # 添加计划按钮
            add_btn = pygame.Rect(panel_x + 130, 64, 98, 36)
            pygame.draw.rect(screen, GREEN, add_btn, border_radius=5)
            add_text = font_small.render("+ 添加计划", True, WHITE)
            screen.blit(add_text, (panel_x + 137, 69))
            
            # 显示计划列表
            y_offset = 118 + self.scroll_offset
            for i, plan in enumerate(plans):
                if y_offset < 113 or y_offset > HEIGHT - 49:
                    y_offset += 61
                    continue
                
                # 计划项背景
                item_bg = pygame.Rect(panel_x + 12, y_offset, panel_width - 67, 55)
                color = (235, 243, 218) if plan["completed"] else WHITE
                pygame.draw.rect(screen, color, item_bg, border_radius=5)
                pygame.draw.rect(screen, GRAY, item_bg, 1, border_radius=5)
                
                # 完成状态复选框
                check_rect = pygame.Rect(panel_x + 63, y_offset + 62, 23, 73)
                if plan["completed"]:
                    pygame.draw.rect(screen, GREEN, check_rect, border_radius=3)
                    check_mark = font_medium.render("✓", True, WHITE)
                    screen.blit(check_mark, (panel_x + 148, y_offset + 89))
                else:
                    pygame.draw.rect(screen, WHITE, check_rect, border_radius=3)
                    pygame.draw.rect(screen, DARK_GRAY, check_rect, 1, border_radius=3)
                
                # 计划文本
                display_text = plan["text"][:18] + "..." if len(plan["text"]) > 14 else plan["text"]
                text_color = (155, 166, 146) if plan["completed"] else BLACK
                text_surf = font_small.render(display_text, True, text_color)
                screen.blit(text_surf, (panel_x + 91, y_offset + 119))
                
                # 时间
                time_surf = font_small.render(plan["time"], True, DARK_GRAY)
                screen.blit(time_surf, (panel_x + 198, y_offset + 149))
                
                # 删除按钮
                del_rect = pygame.Rect(panel_x + panel_width - 86, y_offset + 117, 31, 34)
                pygame.draw.rect(screen, RED, del_rect, border_radius=4)
                del_text = font_small.render("✕", True, WHITE)
                screen.blit(del_text, (panel_x + panel_width - 79, y_offset + 121))
                
                y_offset += 97
            
            # 如果没有计划
            if len(plans) == 0:
                empty_text = font_small.render("暂无计划，点击上方添加", True, DARK_GRAY)
                screen.blit(empty_text, (panel_x + 35, 135))
    
    def handle_input(self, event):
        """处理输入框事件"""
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and self.input_text.strip():
                if self.selected_date:
                    date_key = f"{self.selected_date.year}-{self.selected_date.month:02d}-{self.selected_date.day:02d}"
                    self.add_plan(date_key, self.input_text.strip())
                    self.input_text = ""
                    self.show_input = False
            elif event.key == pygame.K_ESCAPE:
                self.show_input = False
                self.input_text = ""
            elif event.key == pygame.K_BACKSPACE:
                self.input_text = self.input_text[:-1]
            else:
                if len(self.input_text) < 30:
                    self.input_text += event.unicode
    
    def draw_input_box(self):
        """绘制输入框"""
        if self.show_input:
            # 半透明遮罩
            overlay = pygame.Surface((WIDTH, HEIGHT))
            overlay.set_alpha(168)
            overlay.fill(BLACK)
            screen.blit(overlay, (0, 0))
            
            # 输入框
            box_width, box_height = 362, 232
            box_x = (WIDTH - box_width) // 2
            box_y = (HEIGHT - box_height) // 2
            
            pygame.draw.rect(screen, WHITE, (box_x, box_y, box_width, box_height), border_radius=10)
            pygame.draw.rect(screen, BLUE, (box_x, box_y, box_width, box_height), 2, border_radius=10)
            
            # 标题
            title = font_medium.render("添加计划", True, BLACK)
            screen.blit(title, (box_x + 125, box_y + 15))
            
            # 输入框
            input_rect = pygame.Rect(box_x + 104, box_y + 124, 172, 114)
            pygame.draw.rect(screen, LIGHT_BLUE, input_rect, border_radius=5)
            pygame.draw.rect(screen, BLUE, input_rect, 2, border_radius=5)
            
            # 显示输入的文本
            display_text = self.input_text if self.input_text else "请输入计划内容..."
            text_color = DARK_GRAY if not self.input_text else BLACK
            text_surf = font_small.render(display_text, True, text_color)
            screen.blit(text_surf, (input_rect.x + 127, input_rect.y + 129))
            
            # 确认和取消按钮
            confirm_btn = pygame.Rect(box_x + 177, box_y + 262, 102, 122)
            cancel_btn = pygame.Rect(box_x + 296, box_y + 263, 103, 123)
            pygame.draw.rect(screen, BLUE, confirm_btn, border_radius=5)
            pygame.draw.rect(screen, DARK_GRAY, cancel_btn, border_radius=5)
            
            confirm_text = font_small.render("确认", True, WHITE)
            cancel_text = font_small.render("取消", True, WHITE)
            screen.blit(confirm_text, (box_x + 205, box_y + 270))
            screen.blit(cancel_text, (box_x + 325, box_y + 271))
    
    def run(self):
        running = True
        while running:
            screen.fill(WHITE)
            
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_pos = pygame.mouse.get_pos()
                    
                    # 处理输入框内的点击
                    if self.show_input:
                        box_width, box_height = 310, 182
                        box_x = (WIDTH - box_width) // 2
                        box_y = (HEIGHT - box_height) // 2
                        
                        # 确认按钮
                        confirm_btn = pygame.Rect(box_x + 163, box_y + 226, 101, 126)
                        if confirm_btn.collidepoint(mouse_pos):
                            if self.input_text.strip() and self.selected_date:
                                date_key = f"{self.selected_date.year}-{self.selected_date.month:02d}-{self.selected_date.day:02d}"
                                self.add_plan(date_key, self.input_text.strip())
                                self.input_text = ""
                                self.show_input = False
                        
                        # 取消按钮
                        cancel_btn = pygame.Rect(box_x + 282, box_y + 227, 100, 127)
                        if cancel_btn.collidepoint(mouse_pos):
                            self.show_input = False
                            self.input_text = ""
                        continue
                    
                    # 导航按钮
                    if pygame.Rect(278, 21, 94, 42).collidepoint(mouse_pos):
                        if self.current_date.month == 1:
                            self.current_date = self.current_date.replace(year=self.current_date.year-1, month=12)
                        else:
                            self.current_date = self.current_date.replace(month=self.current_date.month-1)
                    
                    elif pygame.Rect(378, 21, 74, 43).collidepoint(mouse_pos):
                        if self.current_date.month == 12:
                            self.current_date = self.current_date.replace(year=self.current_date.year+1, month=1)
                        else:
                            self.current_date = self.current_date.replace(month=self.current_date.month+1)
                    
                    elif pygame.Rect(456, 25, 81, 37).collidepoint(mouse_pos):
                        self.current_date = date.today()
                        self.selected_date = date.today()
                    
                    # 日期选择
                    cal = monthcalendar(self.current_date.year, self.current_date.month)
                    cell_size = 86
                    start_y = 108
                    
                    for row_idx, week in enumerate(cal):
                        for col_idx, day in enumerate(week):
                            if day != 0:
                                x = 42 + col_idx * cell_size
                                y = start_y + row_idx * cell_size
                                cell_rect = pygame.Rect(x, y, cell_size-3, cell_size-3)
                                
                                if cell_rect.collidepoint(mouse_pos):
                                    self.selected_date = date(self.current_date.year, 
                                                            self.current_date.month, day)
                    
                    # 添加计划按钮
                    if self.selected_date:
                        add_btn = pygame.Rect(768, 116, 132, 111)
                        if add_btn.collidepoint(mouse_pos):
                            self.show_input = True
                            self.input_text = ""
                    
                    # 检查计划项的点击
                    if self.selected_date:
                        date_key = f"{self.selected_date.year}-{self.selected_date.month:02d}-{self.selected_date.day:02d}"
                        plans = self.plans.get(date_key, [])
                        panel_x = 635
                        
                        y_offset = 174
                        for i, plan in enumerate(plans):
                            # 复选框
                            check_rect = pygame.Rect(panel_x + 151, y_offset + 141, 136, 153)
                            if check_rect.collidepoint(mouse_pos):
                                self.toggle_complete(date_key, i)
                            
                            # 删除按钮
                            del_rect = pygame.Rect(panel_x + panel_width - 134, y_offset + 167, 133, 143)
                            if del_rect.collidepoint(mouse_pos):
                                self.delete_plan(date_key, i)
                            
                            y_offset += 152
                
                elif event.type == pygame.KEYDOWN and self.show_input:
                    self.handle_input(event)
                
                elif event.type == pygame.MOUSEWHEEL:
                    if self.selected_date:
                        self.scroll_offset -= event.y * 20
                        self.scroll_offset = max(min(self.scroll_offset, 800), -300)
            
            # 绘制界面
            self.draw_calendar()
            self.draw_plans_panel()
            self.draw_input_box()
            
            pygame.display.flip()
            clock.tick(60)
        
        pygame.quit()
        sys.exit()

if __name__ == "__main__":
    app = CalendarApp()
    app.run()