import pygame
import datetime
import json
import os

# 初始化Pygame
pygame.init()
WIDTH, HEIGHT = 900, 650
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)
LIGHT_BLUE = (220, 240, 255)
BLUE = (50, 150, 255)
RED = (220, 60, 60)
GREEN = (40, 180, 80)
ORANGE = (255, 140, 0)

# 中文字体配置（适配Windows/macOS/Linux）
try:
    font_big = pygame.font.SysFont("simhei", 36)
    font_mid = pygame.font.SysFont("simhei", 26)
    font_small = pygame.font.SysFont("simhei", 20)
except:
    font_big = pygame.font.Font(None, 36)
    font_mid = pygame.font.Font(None, 26)
    font_small = pygame.font.Font(None, 20)

# 计划数据文件
DATA_FILE = "plan_data.json"
# 加载保存的计划
def load_plans():
    if os.path.exists(DATA_FILE):
        with open(DATA_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    return {}

# 保存计划到文件
def save_plans(plans):
    with open(DATA_FILE, "w", encoding="utf-8") as f:
        json.dump(plans, f, ensure_ascii=False, indent=2)

plans = load_plans()
current_date = datetime.date.today()
show_input = False
input_text = ""
selected_day = 0
msg_tip = ""

# 获取当月日历信息
def get_month_calendar(year, month):
    first_day = datetime.date(year, month, 1)
    if month == 12:
        next_month = datetime.date(year + 1, 1, 1)
    else:
        next_month = datetime.date(year, month + 1, 1)
    days_count = (next_month - first_day).days
    week_start = first_day.weekday()  # 0周一 ~ 6周日
    return days_count, week_start

# 绘制按钮
def draw_btn(x, y, w, h, text, color):
    pygame.draw.rect(screen, color, (x, y, w, h), border_radius=6)
    pygame.draw.rect(screen, BLACK, (x, y, w, h), 2, border_radius=6)
    text_surf = font_small.render(text, True, WHITE)
    tx = x + (w - text_surf.get_width()) // 2
    ty = y + (h - text_surf.get_height()) // 2
    screen.blit(text_surf, (tx, ty))
    return pygame.Rect(x, y, w, h)

# 主循环
running = True
while running:
    screen.fill(WHITE)
    year = current_date.year
    month = current_date.month
    day = current_date.day

    # 顶部年月标题
    title = font_big.render(f"{year}年{month}月 计划表", True, BLUE)
    screen.blit(title, (30, 15))

    # 左右切换月份按钮
    btn_prev = draw_btn(30, 70, 80, 36, "< 上月", BLUE)
    btn_next = draw_btn(130, 70, 80, 36, "下月 >", BLUE)
    btn_add = draw_btn(240, 70, 110, 36, "新增计划", GREEN)

    # 今日提示
    today_str = f"今日：{datetime.date.today()}"
    tip_surf = font_mid.render(today_str, True, BLACK)
    screen.blit(tip_surf, (400, 72))

    # 星期表头
    week_names = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
    cell_w, cell_h = 105, 80
    start_x, start_y = 30, 130
    for i, wd in enumerate(week_names):
        rect = pygame.Rect(start_x + i*cell_w, start_y, cell_w, 32)
        pygame.draw.rect(screen, GRAY, rect)
        pygame.draw.rect(screen, BLACK, rect, 1)
        wd_text = font_small.render(wd, True, BLACK)
        screen.blit(wd_text, (rect.x+32, rect.y+4))

    # 绘制日历格子
    days_total, week_offset = get_month_calendar(year, month)
    day_num = 1
    for row in range(6):
        for col in range(7):
            x = start_x + col * cell_w
            y = start_y + 32 + row * cell_h
            cell_rect = pygame.Rect(x, y, cell_w, cell_h)
            pygame.draw.rect(screen, LIGHT_BLUE, cell_rect)
            pygame.draw.rect(screen, BLACK, cell_rect, 1)

            # 空白前置天数
            if row == 0 and col < week_offset:
                continue
            if day_num > days_total:
                continue

            # 标记当天
            if day_num == day:
                pygame.draw.rect(screen, (255, 220, 180), cell_rect)
            # 选中日期高亮
            if show_input and day_num == selected_day:
                pygame.draw.rect(screen, (180, 230, 255), cell_rect)

            # 日期数字
            day_text = font_mid.render(str(day_num), True, BLACK)
            screen.blit(day_text, (x+8, y+4))

            # 标记有计划的日期红点
            key = f"{year}-{month:02d}-{day_num:02d}"
            if key in plans and len(plans[key]) > 0:
                pygame.draw.circle(screen, RED, (x+90, y+12), 6)
            day_num += 1

    # 右侧计划面板
    panel_x, panel_y = 760, 130
    panel_w, panel_h = 120, 480
    pygame.draw.rect(screen, GRAY, (panel_x, panel_y, panel_w, panel_h))
    pygame.draw.rect(screen, BLACK, (panel_x, panel_y, panel_w, panel_h), 2)
    panel_title = font_mid.render("当日计划", True, BLACK)
    screen.blit(panel_title, (panel_x+10, panel_y+10))

    # 显示选中日期计划
    if show_input and selected_day > 0:
        key = f"{year}-{month:02d}-{selected_day:02d}"
        plan_list = plans.get(key, [])
        y_off = 45
        for idx, p in enumerate(plan_list):
            p_text = font_small.render(f"{idx+1}.{p}", True, BLACK)
            screen.blit(p_text, (panel_x+6, panel_y+y_off))
            y_off += 28
        # 删除按钮
        if len(plan_list) > 0:
            btn_del = draw_btn(panel_x+8, panel_y+430, 104, 32, "清空计划", RED)
    else:
        hint = font_small.render("点击日期\n新增计划", True, BLACK)
        screen.blit(hint, (panel_x+12, panel_y+60))

    # 底部输入框（新增计划）
    if show_input:
        pygame.draw.rect(screen, GRAY, (30, 560, 720, 60))
        pygame.draw.rect(screen, BLACK, (30, 560, 720, 60), 2)
        input_label = font_mid.render(f"{year}-{month}-{selected_day}：", True, BLACK)
        screen.blit(input_label, (40, 572))
        input_render = font_mid.render(input_text, True, BLUE)
        screen.blit(input_render, (220, 572))
        # 确认、取消按钮
        btn_ok = draw_btn(760, 560, 60, 30, "确定", GREEN)
        btn_cancel = draw_btn(830, 560, 60, 30, "取消", GRAY)

    # 提示消息
    tip_render = font_small.render(msg_tip, True, ORANGE)
    screen.blit(tip_render, (30, 625))

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

        # 鼠标点击
        if event.type == pygame.MOUSEBUTTONDOWN:
            mx, my = event.pos
            # 切换月份
            if btn_prev.collidepoint(mx, my):
                if month == 1:
                    current_date = datetime.date(year-1, 12, 1)
                else:
                    current_date = datetime.date(year, month-1, 1)
                show_input = False
            if btn_next.collidepoint(mx, my):
                if month == 12:
                    current_date = datetime.date(year+1, 1, 1)
                else:
                    current_date = datetime.date(year, month+1, 1)
                show_input = False
            # 新增计划按钮
            if btn_add.collidepoint(mx, my):
                msg_tip = "请先点击日历上的日期"
            # 点击日历格子选择日期
            day_num = 1
            days_total, week_offset = get_month_calendar(year, month)
            for row in range(6):
                for col in range(7):
                    x = start_x + col * cell_w
                    y = start_y + 32 + row * cell_h
                    rect = pygame.Rect(x, y, cell_w, cell_h)
                    if rect.collidepoint(mx, my):
                        if row == 0 and col < week_offset:
                            break
                        if day_num <= days_total:
                            selected_day = day_num
                            show_input = True
                            input_text = ""
                            msg_tip = f"已选择 {year}-{month}-{day_num}，输入事项后点确定"
                        break
                    day_num += 1
            # 输入框确认取消
            if show_input:
                if btn_ok.collidepoint(mx, my) and input_text.strip():
                    key = f"{year}-{month:02d}-{selected_day:02d}"
                    if key not in plans:
                        plans[key] = []
                    plans[key].append(input_text.strip())
                    save_plans(plans)
                    msg_tip = f"成功添加：{input_text}"
                    input_text = ""
                if btn_cancel.collidepoint(mx, my):
                    show_input = False
                    msg_tip = ""
            # 清空当日计划
            if show_input:
                key = f"{year}-{month:02d}-{selected_day:02d}"
                plan_list = plans.get(key, [])
                if len(plan_list) > 0:
                    del_btn_rect = pygame.Rect(panel_x+8, panel_y+430, 104, 32)
                    if del_btn_rect.collidepoint(mx, my):
                        del plans[key]
                        save_plans(plans)
                        msg_tip = f"已清空{year}-{month}-{selected_day}所有计划"

        # 键盘输入文字
        if event.type == pygame.KEYDOWN and show_input:
            if event.key == pygame.K_RETURN:
                # 回车快速确认
                if input_text.strip():
                    key = f"{year}-{month:02d}-{selected_day:02d}"
                    if key not in plans:
                        plans[key] = []
                    plans[key].append(input_text.strip())
                    save_plans(plans)
                    msg_tip = f"成功添加：{input_text}"
                    input_text = ""
            elif event.key == pygame.K_BACKSPACE:
                input_text = input_text[:-1]
            else:
                input_text += event.unicode

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

pygame.quit()