import json
import os
import datetime
import time
import threading
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog

# 数据文件（自动创建）
DATA_FILE = "plans.json"

# ====================== 数据存储 ======================
def load_plans():
    """加载本地计划数据"""
    if not os.path.exists(DATA_FILE):
        return []
    with open(DATA_FILE, "r", encoding="utf-8") as f:
        return json.load(f)

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

# ====================== 提醒线程（后台运行） ======================
def reminder_thread(plans_list, check_interval=60):
    """后台定时检查提醒"""
    while True:
        now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
        for plan in plans_list.copy():
            if plan.get("remind") and plan["remind"] == now and not plan.get("notified"):
                plan["notified"] = True
                save_plans(plans_list)
                messagebox.showinfo("🔔 提醒", f"时间到啦！\n{plan['date']} {plan['title']}")
        time.sleep(check_interval)

# ====================== 主界面 ======================
class PlanCalendarApp:
    def __init__(self, root):
        self.root = root
        self.root.title("📅 日历提醒与计划表")
        self.root.geometry("650x550")

        self.plans = load_plans()

        # 顶部：日期选择
        self.top_frame = ttk.Frame(root)
        self.top_frame.pack(pady=10)

        ttk.Label(self.top_frame, text="选择日期：").grid(row=0, column=0)
        self.date_entry = ttk.Entry(self.top_frame, width=15)
        self.date_entry.grid(row=0, column=1, padx=5)
        self.date_entry.insert(0, datetime.date.today().strftime("%Y-%m-%d"))

        # 按钮
        ttk.Button(self.top_frame, text="📌 添加计划", command=self.add_plan).grid(row=0, column=2, padx=3)
        ttk.Button(self.top_frame, text="🔍 查看当日", command=self.show_by_date).grid(row=0, column=3, padx=3)
        ttk.Button(self.top_frame, text="📋 全部计划", command=self.show_all).grid(row=0, column=4, padx=3)

        # 日历展示
        self.cal_frame = ttk.LabelFrame(root, text="当月日历")
        self.cal_frame.pack(fill="x", padx=10, pady=5)
        self.show_calendar()

        # 计划列表
        self.plan_frame = ttk.LabelFrame(root, text="计划列表")
        self.plan_frame.pack(fill="both", expand=True, padx=10, pady=5)

        columns = ("日期", "时间", "标题", "提醒时间", "操作")
        self.tree = ttk.Treeview(self.plan_frame, columns=columns, show="headings")
        for col in columns:
            self.tree.heading(col, text=col)
            self.tree.column(col, width=110 if col != "标题" else 180)

        self.tree.pack(fill="both", expand=True, pady=5)
        ttk.Button(self.plan_frame, text="🗑 删除选中", command=self.delete_plan).pack(pady=3)

        self.show_all()

    # ====================== 日历 ======================
    def show_calendar(self):
        today = datetime.date.today()
        year = today.year
        month = today.month
        cal_text = self.get_month_calendar(year, month)
        ttk.Label(self.cal_frame, text=cal_text, font=("Consolas", 10)).pack()

    def get_month_calendar(self, year, month):
        first_day = datetime.date(year, month, 1)
        weekday = first_day.weekday()
        days_in_month = [31,28,31,30,31,30,31,31,30,31,30,31]
        if year % 4 == 0 and not year % 100 == 0 or year % 400 == 0:
            days_in_month[1] = 29
        days = days_in_month[month-1]

        cal = f"    {year}年{month:02d}月\n"
        cal += "一 二 三 四 五 六 日\n"
        cal += "   " * weekday

        for d in range(1, days+1):
            cal += f"{d:2} "
            if (weekday + d) % 7 == 0:
                cal += "\n"
        return cal

    # ====================== 计划操作 ======================
    def add_plan(self):
        date = self.date_entry.get().strip()
        try:
            datetime.datetime.strptime(date, "%Y-%m-%d")
        except:
            messagebox.showwarning("格式错误", "请按 YYYY-MM-DD 格式输入")
            return

        title = simpledialog.askstring("新增计划", "计划标题：")
        if not title:
            return

        time_str = simpledialog.askstring("计划时间", "计划时间（HH:MM）：")
        remind = simpledialog.askstring("提醒时间", "提醒时间（YYYY-MM-DD HH:MM）：")

        new_plan = {
            "date": date,
            "time": time_str,
            "title": title,
            "remind": remind,
            "notified": False
        }
        self.plans.append(new_plan)
        save_plans(self.plans)
        self.show_all()
        messagebox.showinfo("成功", "计划已添加 ✅")

    def show_all(self):
        for i in self.tree.get_children():
            self.tree.delete(i)
        for p in self.plans:
            self.tree.insert("", "end", values=(
                p["date"], p.get("time", ""), p["title"], p.get("remind", ""), "双击查看"
            ))

    def show_by_date(self):
        date = self.date_entry.get().strip()
        for i in self.tree.get_children():
            self.tree.delete(i)
        for p in self.plans:
            if p["date"] == date:
                self.tree.insert("", "end", values=(
                    p["date"], p.get("time", ""), p["title"], p.get("remind", ""), "双击查看"
                ))

    def delete_plan(self):
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择一项")
            return
        idx = self.tree.index(selected[0])
        del self.plans[idx]
        save_plans(self.plans)
        self.show_all()

# ====================== 启动 ======================
if __name__ == "__main__":
    plans_data = load_plans()

    # 启动提醒线程
    threading.Thread(target=reminder_thread, args=(plans_data,), daemon=True).start()

    # 启动界面
    window = tk.Tk()
    app = PlanCalendarApp(window)
    window.mainloop()