import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from datetime import datetime
import json
import os

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

# 初始化数据文件
def init_data():
    if not os.path.exists(DATA_FILE):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump({}, f, ensure_ascii=False, indent=2)

# 读取全部计划数据
def load_data():
    with open(DATA_FILE, "r", encoding="utf-8") as f:
        return json.load(f)

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

class CalendarPlanApp:
    def __init__(self, root):
        self.root = root
        self.root.title("日历提醒计划表")
        # ==========修复处：逗号改成字母x，去掉空格==========
        self.root.geometry("820x620")
        self.root.resizable(False, False)
        self.root.configure(bg="#f0f4f8")

        self.current_year = datetime.now().year
        self.current_month = datetime.now().month
        self.selected_date = None  # 选中的日期字符串 yyyy-mm-dd
        self.data = load_data()

        # 界面划分：左侧日历区 + 右侧计划编辑区
        self.left_frame = tk.Frame(root, bg="white", bd=2, relief=tk.GROOVE)
        self.left_frame.place(x=20, y=20, width=380, height=580)

        self.right_frame = tk.Frame(root, bg="white", bd=2, relief=tk.GROOVE)
        self.right_frame.place(x=420, y=20, width=380, height=580)

        self.build_calendar()
        self.build_plan_panel()
        self.refresh_calendar()

    # 构建日历头部（年月切换）
    def build_calendar(self):
        top_frame = tk.Frame(self.left_frame, bg="#3474bb")
        top_frame.pack(fill=tk.X, padx=5, pady=5)

        tk.Button(top_frame, text="<", command=self.last_month, width=3, bg="white").pack(side=tk.LEFT, padx=3)
        self.year_month_label = tk.Label(top_frame, text="", font=("微软雅黑", 13, "bold"), fg="white", bg="#3474bb")
        self.year_month_label.pack(side=tk.LEFT, expand=True)
        tk.Button(top_frame, text=">", command=self.next_month, width=3, bg="white").pack(side=tk.RIGHT, padx=3)

        # 星期表头
        week_frame = tk.Frame(self.left_frame, bg="#e8edf3")
        week_frame.pack(fill=tk.X, padx=5)
        weeks = ["一", "二", "三", "四", "五", "六", "日"]
        for w in weeks:
            tk.Label(week_frame, text=w, width=5, font=("微软雅黑",10), bg="#e8edf3").pack(side=tk.LEFT, padx=1)

        # 日历格子容器
        self.calendar_grid = tk.Frame(self.left_frame, bg="white")
        self.calendar_grid.pack(pady=5)
        self.date_btns = {}  # 存储日期按钮

    # 刷新日历格子
    def refresh_calendar(self):
        # 清空旧按钮
        for widget in self.calendar_grid.winfo_children():
            widget.destroy()
        self.date_btns.clear()

        self.year_month_label.config(text=f"{self.current_year} 年 {self.current_month} 月")
        first_day = datetime(self.current_year, self.current_month, 1)
        # 周一为一周第一天
        first_week_idx = first_day.weekday()
        days_in_month = self.get_month_days(self.current_year, self.current_month)

        day_num = 1
        for row in range(6):
            for col in range(7):
                cell = tk.Frame(self.calendar_grid, width=45, height=45, bg="white")
                cell.grid(row=row, column=col, padx=2, pady=2)
                cell.pack_propagate(False)

                if row == 0 and col < first_week_idx:
                    # 上月空白
                    pass
                elif day_num <= days_in_month:
                    date_str = f"{self.current_year}-{self.current_month:02d}-{day_num:02d}"
                    # 判断当天有无计划，标红圆点
                    has_task = date_str in self.data and len(self.data[date_str]) > 0
                    btn_bg = "#cce0ff" if date_str == self.selected_date else "white"
                    btn = tk.Button(cell, text=str(day_num), bg=btn_bg, relief=tk.FLAT,
                                    command=lambda d=date_str: self.select_date(d))
                    btn.place(x=0, y=0, relwidth=1, relheight=1)
                    if has_task:
                        tk.Label(cell, text="●", fg="red", bg=cell["bg"], font=("",8)).place(x=28, y=0)
                    self.date_btns[date_str] = btn
                    day_num += 1

    # 获取当月总天数
    def get_month_days(self, y, m):
        if m == 12:
            next_m = 1
            next_y = y + 1
        else:
            next_m = m + 1
            next_y = y
        return (datetime(next_y, next_m, 1) - datetime(y, m, 1)).days

    def last_month(self):
        if self.current_month == 1:
            self.current_month = 12
            self.current_year -= 1
        else:
            self.current_month -= 1
        self.refresh_calendar()

    def next_month(self):
        if self.current_month == 12:
            self.current_month = 1
            self.current_year += 1
        else:
            self.current_month += 1
        self.refresh_calendar()

    # 选中日期
    def select_date(self, date_str):
        self.selected_date = date_str
        self.refresh_calendar()
        self.load_day_tasks()

    # 右侧计划面板
    def build_plan_panel(self):
        tk.Label(self.right_frame, text="当日计划表", font=("微软雅黑",12,"bold"), bg="white").pack(pady=8)
        self.date_show = tk.Label(self.right_frame, text="请点击左侧选择日期", fg="#666", bg="white")
        self.date_show.pack()

        # 任务列表框
        list_frame = tk.Frame(self.right_frame, bg="white")
        list_frame.pack(pady=5, fill=tk.BOTH, expand=True, padx=10)
        self.task_list = tk.Listbox(list_frame, height=12, font=("微软雅黑",9))
        scroll = ttk.Scrollbar(list_frame, command=self.task_list.yview)
        self.task_list.config(yscrollcommand=scroll.set)
        self.task_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.task_list.bind("<<ListboxSelect>>", self.on_select_task)

        # 新增任务区域
        add_frame = tk.Frame(self.right_frame, bg="#f7f9fc", padx=8, pady=8)
        add_frame.pack(fill=tk.X, padx=10, pady=5)
        tk.Label(add_frame, text="时间:", bg="#f7f9fc").grid(row=0, column=0, sticky="w")
        self.time_entry = ttk.Entry(add_frame, width=12)
        self.time_entry.grid(row=0, column=1, padx=5)
        tk.Label(add_frame, text="事项:", bg="#f7f9fc").grid(row=0, column=2, sticky="w", padx=(8,0))
        self.title_entry = ttk.Entry(add_frame, width=16)
        self.title_entry.grid(row=0, column=3)

        tk.Label(add_frame, text="备注:", bg="#f7f9fc").grid(row=1, column=0, sticky="w", pady=4)
        self.note_entry = scrolledtext.ScrolledText(add_frame, width=35, height=3, font=("微软雅黑",8))
        self.note_entry.grid(row=1, column=1, columnspan=3, pady=4)

        # 功能按钮
        btn_frame = tk.Frame(self.right_frame, bg="white")
        btn_frame.pack(pady=8)
        ttk.Button(btn_frame, text="添加计划", command=self.add_task).grid(row=0, column=0, padx=4)
        ttk.Button(btn_frame, text="删除选中", command=self.del_task).grid(row=0, column=1, padx=4)
        ttk.Button(btn_frame, text="标记完成", command=self.finish_task).grid(row=0, column=2, padx=4)
        ttk.Button(btn_frame, text="清空输入", command=self.clear_input).grid(row=0, column=3, padx=4)

        self.current_selected_task_idx = None

    # 加载选中日期的所有任务
    def load_day_tasks(self):
        self.task_list.delete(0, tk.END)
        self.clear_input()
        self.date_show.config(text=f"当前日期：{self.selected_date}")
        if not self.selected_date:
            return
        tasks = self.data.get(self.selected_date, [])
        for idx, task in enumerate(tasks):
            status = "✅" if task["finish"] else "⬜"
            text = f"{status} {task['time']} | {task['title']}"
            self.task_list.insert(tk.END, text)

    # 选中列表任务
    def on_select_task(self, event):
        sel = self.task_list.curselection()
        if not sel:
            return
        self.current_selected_task_idx = sel[0]
        task = self.data[self.selected_date][self.current_selected_task_idx]
        self.time_entry.delete(0, tk.END)
        self.time_entry.insert(0, task["time"])
        self.title_entry.delete(0, tk.END)
        self.title_entry.insert(0, task["title"])
        self.note_entry.delete("1.0", tk.END)
        self.note_entry.insert("1.0", task["note"])

    # 新增任务
    def add_task(self):
        if not self.selected_date:
            messagebox.showwarning("提示", "请先在左侧日历选择日期！")
            return
        t = self.time_entry.get().strip()
        title = self.title_entry.get().strip()
        note = self.note_entry.get("1.0", tk.END).strip()
        if not t or not title:
            messagebox.showwarning("提示", "时间和事项不能为空！")
            return
        new_task = {
            "time": t,
            "title": title,
            "note": note,
            "finish": False
        }
        if self.selected_date not in self.data:
            self.data[self.selected_date] = []
        self.data[self.selected_date].append(new_task)
        save_data(self.data)
        self.load_day_tasks()
        self.clear_input()

    # 删除任务
    def del_task(self):
        if self.current_selected_task_idx is None:
            messagebox.showinfo("提示", "请选中一条计划")
            return
        del self.data[self.selected_date][self.current_selected_task_idx]
        if len(self.data[self.selected_date]) == 0:
            del self.data[self.selected_date]
        save_data(self.data)
        self.load_day_tasks()
        self.current_selected_task_idx = None
        self.refresh_calendar()

    # 标记完成
    def finish_task(self):
        if self.current_selected_task_idx is None:
            messagebox.showinfo("提示", "请选中一条计划")
            return
        task = self.data[self.selected_date][self.current_selected_task_idx]
        task["finish"] = not task["finish"]
        save_data(self.data)
        self.load_day_tasks()

    # 清空输入框
    def clear_input(self):
        self.time_entry.delete(0, tk.END)
        self.title_entry.delete(0, tk.END)
        self.note_entry.delete("1.0", tk.END)
        self.current_selected_task_idx = None

if __name__ == "__main__":
    init_data()
    root = tk.Tk()
    app = CalendarPlanApp(root)
    root.mainloop()