import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import calendar
import datetime
import json
import os

# 数据保存路径
DATA_FILE = "calendar_planner_data.json"


class CalendarPlannerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("日历提醒与计划表")
        self.root.geometry("800x600")
        self.root.resizable(True, True)

        # 初始化当前日期
        self.today = datetime.date.today()
        self.current_year = self.today.year
        self.current_month = self.today.month

        # 加载本地数据
        self.planner_data = self.load_data()

        # 创建界面布局
        self.create_widgets()
        # 初始化日历显示
        self.update_calendar()

    def load_data(self):
        """加载本地保存的计划数据"""
        if os.path.exists(DATA_FILE):
            try:
                with open(DATA_FILE, "r", encoding="utf-8") as f:
                    return json.load(f)
            except:
                return {}
        return {}

    def save_data(self):
        """保存计划数据到本地文件"""
        try:
            with open(DATA_FILE, "w", encoding="utf-8") as f:
                json.dump(self.planner_data, f, ensure_ascii=False, indent=4)
            return True
        except Exception as e:
            messagebox.showerror("保存失败", f"数据保存出错：{str(e)}")
            return False

    def create_widgets(self):
        """创建界面组件"""
        # 顶部导航栏（年月切换 + 今日按钮）
        nav_frame = ttk.Frame(self.root)
        nav_frame.pack(fill=tk.X, padx=10, pady=5)

        # 上一月按钮
        ttk.Button(nav_frame, text="◀ 上一月", command=self.prev_month).pack(
            side=tk.LEFT, padx=5)

        # 年月显示
        self.year_month_label = ttk.Label(
            nav_frame, text=f"{self.current_year}年{self.current_month}月", font=("SimHei", 14))
        self.year_month_label.pack(side=tk.LEFT, padx=20)

        # 下一月按钮
        ttk.Button(nav_frame, text="下一月 ▶", command=self.next_month).pack(
            side=tk.LEFT, padx=5)

        # 今日按钮
        ttk.Button(nav_frame, text="回到今日", command=self.goto_today).pack(
            side=tk.RIGHT, padx=5)

        # 日历显示区域
        self.calendar_frame = ttk.Frame(self.root)
        self.calendar_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # 计划操作区域
        op_frame = ttk.Frame(self.root)
        op_frame.pack(fill=tk.X, padx=10, pady=5)

        # 添加计划按钮
        ttk.Button(op_frame, text="添加计划/提醒",
                   command=self.add_plan).pack(side=tk.LEFT, padx=5)

        # 查看计划按钮
        ttk.Button(op_frame, text="查看当日计划", command=self.view_plans).pack(
            side=tk.LEFT, padx=5)

        # 删除计划按钮
        ttk.Button(op_frame, text="删除当日计划", command=self.delete_plan).pack(
            side=tk.LEFT, padx=5)

    def update_calendar(self):
        """更新日历显示"""
        # 清空原有日历组件
        for widget in self.calendar_frame.winfo_children():
            widget.destroy()

        # 设置星期表头
        weekdays = ["日", "一", "二", "三", "四", "五", "六"]
        for i, day in enumerate(weekdays):
            lbl = ttk.Label(self.calendar_frame, text=day,
                            font=("SimHei", 10, "bold"))
            lbl.grid(row=0, column=i, sticky="nsew", padx=2, pady=2)

        # 获取当月日历数据
        cal = calendar.monthcalendar(self.current_year, self.current_month)

        # 配置列权重（让日期格子均匀分布）
        for i in range(7):
            self.calendar_frame.grid_columnconfigure(i, weight=1)

        # 显示日期格子
        for row_idx, week in enumerate(cal):
            for col_idx, day in enumerate(week):
                # 空日期（上月/下月）
                if day == 0:
                    lbl = ttk.Label(self.calendar_frame,
                                    text="", relief=tk.RIDGE)
                else:
                    # 标记今日
                    is_today = (day == self.today.day and
                                self.current_month == self.today.month and
                                self.current_year == self.today.year)

                    # 检查该日期是否有计划
                    date_key = f"{self.current_year}-{self.current_month:02d}-{day:02d}"
                    has_plan = date_key in self.planner_data and len(
                        self.planner_data[date_key]) > 0

                    # 设置样式
                    font_style = ("SimHei", 12, "bold") if is_today else (
                        "SimHei", 10)
                    bg_color = "#e6f7ff" if is_today else "#f0f0f0" if has_plan else "white"

                    lbl = tk.Label(self.calendar_frame, text=str(day), font=font_style,
                                   bg=bg_color, relief=tk.RIDGE)

                    # 绑定点击事件（选中日期）
                    lbl.bind("<Button-1>", lambda e,
                             d=day: self.select_date(d))
                    self.selected_day = day  # 默认选中当月某天

                lbl.grid(row=row_idx+1, column=col_idx,
                         sticky="nsew", padx=2, pady=2)
                self.calendar_frame.grid_rowconfigure(row_idx+1, weight=1)

        # 更新年月标签
        self.year_month_label.config(
            text=f"{self.current_year}年{self.current_month}月")

    def select_date(self, day):
        """选中指定日期"""
        self.selected_day = day
        messagebox.showinfo(
            "提示", f"已选中 {self.current_year}年{self.current_month}月{day}日")

    def prev_month(self):
        """切换到上一月"""
        if self.current_month == 1:
            self.current_month = 12
            self.current_year -= 1
        else:
            self.current_month -= 1
        self.update_calendar()

    def next_month(self):
        """切换到下一月"""
        if self.current_month == 12:
            self.current_month = 1
            self.current_year += 1
        else:
            self.current_month += 1
        self.update_calendar()

    def goto_today(self):
        """回到今日日期"""
        self.current_year = self.today.year
        self.current_month = self.today.month
        self.update_calendar()

    def add_plan(self):
        """添加计划/提醒"""
        # 生成选中日期的键
        date_key = f"{self.current_year}-{self.current_month:02d}-{self.selected_day:02d}"

        # 弹出输入框获取计划内容
        plan_content = simpledialog.askstring("添加计划", f"请输入{date_key}的计划/提醒：")
        if not plan_content:
            return  # 用户取消输入

        # 初始化该日期的计划列表
        if date_key not in self.planner_data:
            self.planner_data[date_key] = []

        # 添加计划并保存
        self.planner_data[date_key].append(plan_content)
        if self.save_data():
            messagebox.showinfo("成功", "计划添加完成！")
            self.update_calendar()  # 刷新日历（标记有计划的日期）

    def view_plans(self):
        """查看选中日期的计划"""
        date_key = f"{self.current_year}-{self.current_month:02d}-{self.selected_day:02d}"

        # 检查是否有计划
        if date_key not in self.planner_data or len(self.planner_data[date_key]) == 0:
            messagebox.showinfo("提示", f"{date_key}暂无计划/提醒")
            return

        # 拼接计划内容
        plan_text = f"{date_key} 的计划/提醒：\n"
        for idx, plan in enumerate(self.planner_data[date_key], 1):
            plan_text += f"{idx}. {plan}\n"

        # 显示计划
        messagebox.showinfo("当日计划", plan_text)

    def delete_plan(self):
        """删除选中日期的计划"""
        date_key = f"{self.current_year}-{self.current_month:02d}-{self.selected_day:02d}"

        # 检查是否有计划
        if date_key not in self.planner_data or len(self.planner_data[date_key]) == 0:
            messagebox.showinfo("提示", f"{date_key}暂无计划/提醒可删除")
            return

        # 确认删除
        if not messagebox.askyesno("确认删除", f"是否删除{date_key}的所有计划/提醒？"):
            return

        # 删除计划并保存
        del self.planner_data[date_key]
        if self.save_data():
            messagebox.showinfo("成功", "计划删除完成！")
            self.update_calendar()  # 刷新日历


if __name__ == "__main__":
    root = tk.Tk()
    app = CalendarPlannerApp(root)
    root.mainloop()
