import tkinter as tk
from tkinter import ttk, messagebox
import calendar
import time
import threading
from datetime import datetime, timedelta
import json
import os

DATA_FILE = "plans.json"

class CalendarApp:
    def __init__(self, root):
        self.root = root
        self.root.title("019. 日历提醒与计划表")
        self.root.geometry("750x580")
        self.root.resizable(False, False)

        self.now = datetime.now()
        self.current_year = self.now.year
        self.current_month = self.now.month
        self.selected_date = None
        self.plans = self.load_plans()
        self.reminder_thread = None

        self.build_ui()
        self.draw_calendar()
        self.start_reminder()

    # ==================== 数据持久化 ====================
    def load_plans(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_plans(self):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(self.plans, f, ensure_ascii=False, indent=2)

    # ==================== UI 构建 ====================
    def build_ui(self):
        # ===== 顶部：年月导航 =====
        top = tk.Frame(self.root)
        top.pack(pady=10)

        tk.Button(top, text="◀", width=3, command=self.prev_month).pack(side=tk.LEFT, padx=5)
        self.title_label = tk.Label(top, text="", font=("微软雅黑", 16, "bold"))
        self.title_label.pack(side=tk.LEFT, padx=20)
        tk.Button(top, text="▶", width=3, command=self.next_month).pack(side=tk.LEFT, padx=5)

        # ===== 左侧：日历区 =====
        cal_frame = tk.Frame(self.root)
        cal_frame.pack(side=tk.LEFT, padx=15, pady=5)

        # 星期标题
        weekdays = ["一", "二", "三", "四", "五", "六", "日"]
        for i, w in enumerate(weekdays):
            tk.Label(cal_frame, text=w, width=8, font=("微软雅黑", 10, "bold"),
                      fg="#666").grid(row=0, column=i)

        # 日期按钮（7x7 网格）
        self.day_buttons = []
        for r in range(1, 8):
            row = []
            for c in range(7):
                btn = tk.Button(
                    cal_frame, text="", width=8, height=2,
                    command=lambda r=r, c=c: self.select_date(r, c)
                )
                btn.grid(row=r, column=c, padx=1, pady=1)
                row.append(btn)
            self.day_buttons.append(row)

        # ===== 右侧：计划管理区 =====
        right = tk.Frame(self.root)
        right.pack(side=tk.LEFT, padx=10, fill=tk.BOTH, expand=True)

        # 选中日期
        self.date_label = tk.Label(right, text="请选择日期", font=("微软雅黑", 12, "bold"))
        self.date_label.pack(anchor="w", pady=5)

        # 添加计划
        add_frame = tk.Frame(right)
        add_frame.pack(fill=tk.X, pady=5)

        tk.Label(add_frame, text="时间:").pack(side=tk.LEFT)
        self.time_entry = tk.Entry(add_frame, width=6)
        self.time_entry.pack(side=tk.LEFT, padx=2)
        self.time_entry.insert(0, "12:00")

        tk.Label(add_frame, text=" 内容:").pack(side=tk.LEFT)
        self.content_entry = tk.Entry(add_frame, width=18)
        self.content_entry.pack(side=tk.LEFT, padx=2)

        tk.Button(add_frame, text="添加", bg="#4CAF50", fg="white",
                  command=self.add_plan).pack(side=tk.LEFT, padx=5)

        # 计划列表
        tk.Label(right, text="— 当日计划 —", font=("微软雅黑", 10)).pack(anchor="w", pady=(10, 2))

        self.plan_list = tk.Listbox(right, width=35, height=15, font=("Consolas", 10))
        self.plan_list.pack(fill=tk.BOTH, expand=True)

        tk.Button(right, text="删除选中", bg="#f44336", fg="white",
                  command=self.delete_plan).pack(pady=5)

    # ==================== 日历绘制 ====================
    def draw_calendar(self):
        self.title_label.config(text=f"{self.current_year}年 {self.current_month}月")

        cal = calendar.monthcalendar(self.current_year, self.current_month)
        today = datetime.now()

        for r in range(7):
            for c in range(7):
                btn = self.day_buttons[r][c]
                btn.config(text="", bg="SystemButtonFace", fg="black")
                btn.config(state="normal")

        for week_idx, week in enumerate(cal):
            for day_idx, day in enumerate(week):
                if day == 0:
                    continue
                btn = self.day_buttons[week_idx][day_idx]
                btn.config(text=str(day))

                # 今天高亮
                if (day == today.day and
                    self.current_month == today.month and
                    self.current_year == today.year):
                    btn.config(bg="#2196F3", fg="white")

                # 有计划的日期标记
                date_str = f"{self.current_year}-{self.current_month:02d}-{day:02d}"
                if date_str in self.plans and self.plans[date_str]:
                    if day != today.day:
                        btn.config(bg="#C8E6C9")

    def prev_month(self):
        self.current_month -= 1
        if self.current_month < 1:
            self.current_month = 12
            self.current_year -= 1
        self.draw_calendar()

    def next_month(self):
        self.current_month += 1
        if self.current_month > 12:
            self.current_month = 1
            self.current_year += 1
        self.draw_calendar()

    # ==================== 日期选择 ====================
    def select_date(self, row, col):
        week = calendar.monthcalendar(self.current_year, self.current_month)
        if row - 1 < len(week) and col < len(week[row - 1]):
            day = week[row - 1][col]
            if day == 0:
                return
            self.selected_date = f"{self.current_year}-{self.current_month:02d}-{day:02d}"
            weekday_names = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
            wd = weekday_names[col]
            self.date_label.config(text=f"{self.selected_date}  {wd}")
            self.refresh_plan_list()

    # ==================== 计划管理 ====================
    def add_plan(self):
        if not self.selected_date:
            messagebox.showwarning("提示", "请先选择日期！")
            return

        time_str = self.time_entry.get().strip()
        content = self.content_entry.get().strip()

        if not content:
            messagebox.showwarning("提示", "请输入计划内容！")
            return

        # 验证时间格式
        try:
            datetime.strptime(time_str, "%H:%M")
        except:
            messagebox.showwarning("提示", "时间格式错误！请用 HH:MM 格式")
            return

        plan = {"time": time_str, "content": content}

        if self.selected_date not in self.plans:
            self.plans[self.selected_date] = []
        self.plans[self.selected_date].append(plan)

        # 按时间排序
        self.plans[self.selected_date].sort(key=lambda x: x["time"])

        self.save_plans()
        self.content_entry.delete(0, tk.END)
        self.refresh_plan_list()
        self.draw_calendar()

        messagebox.showinfo("成功", "计划已添加！")

    def delete_plan(self):
        sel = self.plan_list.curselection()
        if not sel:
            return
        idx = sel[0]

        if self.selected_date and self.selected_date in self.plans:
            del self.plans[self.selected_date][idx]
            if not self.plans[self.selected_date]:
                del self.plans[self.selected_date]
            self.save_plans()
            self.refresh_plan_list()
            self.draw_calendar()

    def refresh_plan_list(self):
        self.plan_list.delete(0, tk.END)
        if self.selected_date and self.selected_date in self.plans:
            for p in self.plans[self.selected_date]:
                self.plan_list.insert(tk.END, f"  {p['time']}  {p['content']}")

    # ==================== 提醒功能 ====================
    def start_reminder(self):
        def check():
            while True:
                now = datetime.now()
                now_str = now.strftime("%Y-%m-%d")
                time_str = now.strftime("%H:%M")

                if now_str in self.plans:
                    for plan in self.plans[now_str]:
                        # 每分钟检查一次，避免重复提醒
                        plan_key = f"{now_str} {plan['time']}"
                        if plan_key == f"{now_str} {time_str}":
                            self.root.after(0, lambda p=plan: self.show_reminder(p))
                time.sleep(30)

        self.reminder_thread = threading.Thread(target=check, daemon=True)
        self.reminder_thread.start()

    def show_reminder(self, plan):
        messagebox.showinfo(
            "⏰ 计划提醒",
            f"时间到！\n\n📌 {plan['content']}"
        )


if __name__ == "__main__":
    root = tk.Tk()
    app = CalendarApp(root)
    root.mainloop()