import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import os
import datetime
import random
import math

# ========================
# 全局配置
# ========================
WIDTH, HEIGHT = 1000, 700
DATA_FILE = "study_data.json"

# ========================
# 全局状态
# ========================
tasks = []          # {id, title, subject, priority, duration, done, date, notes, pomodoro_count}
subjects = ["📐 数学", "📖 语文", "🔬 物理", "🧪 化学", "🌍 英语", "💻 编程", "📚 其他"]
current_date = datetime.date.today()
selected_task_id = None
pomodoro_running = False
pomodoro_time = 25 * 60  # 默认25分钟
pomodoro_remaining = 25 * 60
pomodoro_mode = "focus"  # focus / break
pomodoro_task_id = None
stats_cache = {}

# ========================
# 数据持久化
# ========================
def save_data():
    data = {
        "tasks": tasks,
        "subjects": subjects,
        "stats_cache": stats_cache,
    }
    try:
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    except Exception:
        pass

def load_data():
    global tasks, subjects, stats_cache
    if os.path.exists(DATA_FILE):
        try:
            with open(DATA_FILE, "r", encoding="utf-8") as f:
                data = json.load(f)
            tasks = data.get("tasks", [])
            subjects = data.get("subjects", subjects)
            stats_cache = data.get("stats_cache", {})
        except Exception:
            pass

# ========================
# Tkinter 主窗口
# ========================
root = tk.Tk()
root.title("📅 每日学习计划 · StudyPlanner")
root.geometry(f"{WIDTH}x{HEIGHT}")
root.minsize(900, 650)

# 字体
FONT_TITLE = ("Microsoft YaHei UI", 16, "bold")
FONT_SUB = ("Microsoft YaHei UI", 11)
FONT_BODY = ("Microsoft YaHei UI", 10)
FONT_SM = ("Microsoft YaHei UI", 9)
FONT_MONO = ("Consolas", 10)

# 颜色主题
THEME = {
    "bg": "#F5F7FA",
    "panel": "#FFFFFF",
    "accent": "#4A6CF7",
    "accent_light": "#E8EDFE",
    "green": "#22C55E",
    "green_light": "#DCFCE7",
    "orange": "#F59E0B",
    "orange_light": "#FEF3C7",
    "red": "#EF4444",
    "red_light": "#FEE2E2",
    "purple": "#8B5CF6",
    "purple_light": "#EDE9FE",
    "text": "#1E293B",
    "text_sec": "#64748B",
    "border": "#E2E8F0",
    "done": "#94A3B8",
    "high": "#EF4444",
    "mid": "#F59E0B",
    "low": "#22C55E",
}

root.configure(bg=THEME["bg"])

# ========================
# 样式
# ========================
style = ttk.Style()
style.theme_use("clam")
style.configure("TFrame", background=THEME["bg"])
style.configure("Panel.TFrame", background=THEME["panel"])
style.configure("TLabel", background=THEME["bg"], foreground=THEME["text"])
style.configure("Panel.TLabel", background=THEME["panel"], foreground=THEME["text"])
style.configure("TButton",
                background=THEME["accent"], foreground="white",
                font=FONT_BODY, borderwidth=0, relief="flat")
style.map("TButton",
           background=[("active", "#3B5BDB"), ("pressed", "#364FC7")])
style.configure("Green.TButton",
                background=THEME["green"], foreground="white",
                font=FONT_BODY, borderwidth=0)
style.map("Green.TButton",
           background=[("active", "#16A34A"), ("pressed", "#15803D")])
style.configure("Orange.TButton",
                background=THEME["orange"], foreground="white",
                font=FONT_BODY, borderwidth=0)
style.configure("Outline.TButton",
                background=THEME["panel"], foreground=THEME["accent"],
                font=FONT_BODY, borderwidth=1, relief="solid")
style.configure("TEntry", font=FONT_BODY)
style.configure("TCombobox", font=FONT_BODY)

# ========================
# 工具函数
# ========================
def date_to_str(d):
    return d.strftime("%Y-%m-%d")

def str_to_date(s):
    return datetime.date.fromisoformat(s)

def get_today_tasks():
    today = date_to_str(current_date)
    return [t for t in tasks if t.get("date", "") == today]

def get_task_by_id(tid):
    for t in tasks:
        if t["id"] == tid:
            return t
    return None

def gen_id():
    return str(int(datetime.datetime.now().timestamp() * 1000))

def priority_color(p):
    return {"high": THEME["high"], "mid": THEME["mid"], "low": THEME["low"]}.get(p, THEME["text_sec"])

def priority_text(p):
    return {"high": "🔴 高", "mid": "🟡 中", "low": "🟢 低"}.get(p, "—")

def format_time(seconds):
    m, s = divmod(int(seconds), 60)
    return f"{m:02d}:{s:02d}"

# ========================
# 布局：顶部栏
# ========================
top_bar = tk.Frame(root, bg=THEME["accent"], height=56)
top_bar.pack(fill="x")
top_bar.pack_propagate(False)

tk.Label(top_bar, text="📅 每日学习计划", font=FONT_TITLE,
         bg=THEME["accent"], fg="white").pack(side="left", padx=20, pady=10)

date_label = tk.Label(top_bar, text="", font=FONT_SUB,
                       bg=THEME["accent"], fg="white")
date_label.pack(side="right", padx=20)

# ========================
# 布局：主内容区
# ========================
main_area = tk.Frame(root, bg=THEME["bg"])
main_area.pack(fill="both", expand=True, padx=12, pady=8)

# 左列：任务列表
left_col = tk.Frame(main_area, bg=THEME["bg"], width=420)
left_col.pack(side="left", fill="both", expand=True, padx=(0, 6))
left_col.pack_propagate(False)

# 右列：番茄钟 + 统计
right_col = tk.Frame(main_area, bg=THEME["bg"], width=380)
right_col.pack(side="right", fill="both", expand=True, padx=(6, 0))
right_col.pack_propagate(False)

# ========================
# 左列 - 日期切换 + 添加任务
# ========================
date_nav = tk.Frame(left_col, bg=THEME["bg"])
date_nav.pack(fill="x", pady=(0, 8))

tk.Button(date_nav, text="◀ 前一天", font=FONT_SM,
           bg=THEME["panel"], fg=THEME["accent"],
           relief="flat", padx=10, pady=4,
           command=lambda: change_date(-1)).pack(side="left")

today_btn = tk.Button(date_nav, text="📍 今天", font=FONT_SM,
                       bg=THEME["accent"], fg="white",
                       relief="flat", padx=12, pady=4,
                       command=lambda: goto_today())
today_btn.pack(side="left", padx=6)

tk.Button(date_nav, text="后一天 ▶", font=FONT_SM,
           bg=THEME["panel"], fg=THEME["accent"],
           relief="flat", padx=10, pady=4,
           command=lambda: change_date(1)).pack(side="left")

# 日期显示
current_date_label = tk.Label(date_nav, text="", font=FONT_SUB,
                                bg=THEME["bg"], fg=THEME["text"])
current_date_label.pack(side="left", padx=12)

# 添加任务区
add_frame = tk.LabelFrame(left_col, text="  ➕ 添加新任务  ", font=FONT_SM,
                           bg=THEME["panel"], fg=THEME["accent"],
                           relief="flat", bd=1, highlightcolor=THEME["accent"])
add_frame.pack(fill="x", pady=(0, 8), ipady=6)

tk.Label(add_frame, text="任务名:", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).grid(row=0, column=0, padx=8, pady=4, sticky="w")
task_entry = tk.Entry(add_frame, font=FONT_BODY, relief="solid", bd=1, highlightcolor=THEME["accent"])
task_entry.grid(row=0, column=1, padx=4, pady=4, sticky="we")

tk.Label(add_frame, text="科目:", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).grid(row=0, column=2, padx=8, pady=4, sticky="w")
subject_var = tk.StringVar(value=subjects[0])
subject_combo = ttk.Combobox(add_frame, textvariable=subject_var,
                              values=subjects, font=FONT_SM, width=10, state="readonly")
subject_combo.grid(row=0, column=3, padx=4, pady=4)

tk.Label(add_frame, text="优先级:", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).grid(row=1, column=0, padx=8, pady=4, sticky="w")
priority_var = tk.StringVar(value="mid")
prio_frame = tk.Frame(add_frame, bg=THEME["panel"])
prio_frame.grid(row=1, column=1, padx=4, pady=4, sticky="w")
for txt, val in [("🔴 高", "high"), ("🟡 中", "mid"), ("🟢 低", "low")]:
    tk.Radiobutton(prio_frame, text=txt, variable=priority_var, value=val,
                    font=FONT_SM, bg=THEME["panel"], selectcolor=THEME["accent_light"]
                    ).pack(side="left", padx=4)

tk.Label(add_frame, text="时长(分):", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).grid(row=1, column=2, padx=8, pady=4, sticky="w")
duration_var = tk.StringVar(value="30")
tk.Entry(add_frame, textvariable=duration_var, font=FONT_SM, width=6,
         relief="solid", bd=1).grid(row=1, column=3, padx=4, pady=4, sticky="w")

add_btn = tk.Button(add_frame, text="✅ 添加任务", font=FONT_SUB,
                     bg=THEME["green"], fg="white", relief="flat", padx=16, pady=4,
                     command=lambda: add_task())
add_btn.grid(row=2, column=0, columnspan=4, pady=8)

add_frame.columnconfigure(1, weight=1)

# 任务列表
list_frame = tk.Frame(left_col, bg=THEME["bg"])
list_frame.pack(fill="both", expand=True)

tk.Label(list_frame, text="📋 今日任务", font=FONT_SUB,
         bg=THEME["bg"], fg=THEME["text"]).pack(anchor="w", pady=(0, 4))

# Canvas + Scrollbar for task list
task_canvas = tk.Canvas(list_frame, bg=THEME["bg"], highlightthickness=0)
task_scrollbar = tk.Scrollbar(list_frame, orient="vertical", command=task_canvas.yview)
task_canvas.configure(yscrollcommand=task_scrollbar.set)

task_scrollbar.pack(side="right", fill="y")
task_canvas.pack(side="left", fill="both", expand=True)

task_list_inner = tk.Frame(task_canvas, bg=THEME["bg"])
task_window = task_canvas.create_window((0, 0), window=task_list_inner, anchor="nw")

def on_task_canvas_configure(e):
    task_canvas.configure(scrollregion=task_canvas.bbox("all"))
task_list_inner.bind("<Configure>", on_task_canvas_configure)

# ========================
# 右列 - 番茄钟
# ========================
pomo_frame = tk.LabelFrame(right_col, text="  🍅 番茄钟  ", font=FONT_SM,
                            bg=THEME["panel"], fg=THEME["accent"],
                            relief="flat", bd=1)
pomo_frame.pack(fill="x", pady=(0, 8), ipady=8)

pomo_time_label = tk.Label(pomo_frame, text="25:00", font=("Consolas", 36, "bold"),
                            bg=THEME["panel"], fg=THEME["accent"])
pomo_time_label.pack(pady=(4, 0))

pomo_status = tk.Label(pomo_frame, text="⏸️ 已停止", font=FONT_SM,
                        bg=THEME["panel"], fg=THEME["text_sec"])
pomo_status.pack()

pomo_task_label = tk.Label(pomo_frame, text="未关联任务", font=FONT_SM,
                            bg=THEME["panel"], fg=THEME["text_sec"])
pomo_task_label.pack(pady=(2, 4))

pomo_btn_frame = tk.Frame(pomo_frame, bg=THEME["panel"])
pomo_btn_frame.pack(pady=4)

tk.Button(pomo_btn_frame, text="▶ 开始", font=FONT_SM,
          bg=THEME["green"], fg="white", relief="flat", padx=12,
          command=lambda: start_pomodoro()).pack(side="left", padx=4)

tk.Button(pomo_btn_frame, text="⏸ 暂停", font=FONT_SM,
          bg=THEME["orange"], fg="white", relief="flat", padx=12,
          command=lambda: pause_pomodoro()).pack(side="left", padx=4)

tk.Button(pomo_btn_frame, text="⏹ 重置", font=FONT_SM,
          bg=THEME["red"], fg="white", relief="flat", padx=12,
          command=lambda: reset_pomodoro()).pack(side="left", padx=4)

# 番茄设置
pomo_set_frame = tk.Frame(pomo_frame, bg=THEME["panel"])
pomo_set_frame.pack(pady=(4, 0))

tk.Label(pomo_set_frame, text="专注:", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).pack(side="left", padx=4)
pomo_focus_var = tk.StringVar(value="25")
tk.Entry(pomo_set_frame, textvariable=pomo_focus_var, font=FONT_SM, width=4,
         relief="solid", bd=1).pack(side="left", padx=2)

tk.Label(pomo_set_frame, text="休息:", font=FONT_SM,
         bg=THEME["panel"], fg=THEME["text_sec"]).pack(side="left", padx=(8, 4))
pomo_break_var = tk.StringVar(value="5")
tk.Entry(pomo_set_frame, textvariable=pomo_break_var, font=FONT_SM, width=4,
         relief="solid", bd=1).pack(side="left", padx=2)

# ========================
# 右列 - 统计面板
# ========================
stats_frame = tk.LabelFrame(right_col, text="  📊 学习统计  ", font=FONT_SM,
                             bg=THEME["panel"], fg=THEME["accent"],
                             relief="flat", bd=1)
stats_frame.pack(fill="both", expand=True, pady=(0, 8), ipady=4)

stats_canvas = tk.Canvas(stats_frame, bg=THEME["panel"], highlightthickness=0)
stats_canvas.pack(fill="both", expand=True, padx=8, pady=4)

# ========================
# 底部状态栏
# ========================
status_bar = tk.Frame(root, bg=THEME["panel"], height=28)
status_bar.pack(fill="x", side="bottom")
status_bar.pack_propagate(False)

status_label = tk.Label(status_bar, text="", font=FONT_SM,
                        bg=THEME["panel"], fg=THEME["text_sec"])
status_label.pack(side="left", padx=12)

# ========================
# 任务操作函数
# ========================
def add_task():
    title = task_entry.get().strip()
    if not title:
        messagebox.showwarning("提示", "请输入任务名称！")
        return
    try:
        dur = int(duration_var.get())
        if dur <= 0:
            dur = 30
    except ValueError:
        dur = 30

    task = {
        "id": gen_id(),
        "title": title,
        "subject": subject_var.get(),
        "priority": priority_var.get(),
        "duration": dur,
        "done": False,
        "date": date_to_str(current_date),
        "notes": "",
        "pomodoro_count": 0,
        "created_at": datetime.datetime.now().isoformat(),
    }
    tasks.append(task)
    task_entry.delete(0, "end")
    duration_var.set("30")
    priority_var.set("mid")
    save_data()
    refresh_all()
    status_label.config(text=f"✅ 已添加任务: {title}")

def toggle_task(tid):
    t = get_task_by_id(tid)
    if t:
        t["done"] = not t["done"]
        if t["done"]:
            t["pomodoro_count"] = t.get("pomodoro_count", 0) + 0
            status_label.config(text=f"🎉 完成: {t['title']}")
        else:
            status_label.config(text=f"↩️ 撤销: {t['title']}")
        save_data()
        refresh_all()

def delete_task(tid):
    global selected_task_id
    t = get_task_by_id(tid)
    if not t:
        return
    if messagebox.askyesno("确认", f"删除任务「{t['title']}」？"):
        tasks[:] = [x for x in tasks if x["id"] != tid]
        if selected_task_id == tid:
            selected_task_id = None
        save_data()
        refresh_all()
        status_label.config(text=f"🗑️ 已删除: {t['title']}")

def edit_task(tid):
    t = get_task_by_id(tid)
    if not t:
        return
    new_title = simpledialog.askstring("编辑任务", "任务名称:", initialvalue=t["title"])
    if new_title and new_title.strip():
        t["title"] = new_title.strip()
        save_data()
        refresh_all()
        status_label.config(text=f"✏️ 已更新: {t['title']}")

def add_note(tid):
    t = get_task_by_id(tid)
    if not t:
        return
    note = simpledialog.askstring("添加笔记", f"给「{t['title']}」添加笔记:",
                                   initialvalue=t.get("notes", ""))
    if note is not None:
        t["notes"] = note
        save_data()
        refresh_all()

# ========================
# 日期导航
# ========================
def change_date(delta):
    global current_date
    current_date += datetime.timedelta(days=delta)
    refresh_all()

def goto_today():
    global current_date
    current_date = datetime.date.today()
    refresh_all()

# ========================
# 番茄钟
# ========================
def start_pomodoro():
    global pomodoro_running, pomodoro_task_id
    if pomodoro_running:
        return
    if selected_task_id:
        pomodoro_task_id = selected_task_id
        t = get_task_by_id(selected_task_id)
        if t:
            pomo_task_label.config(text=f"关联: {t['title']}")
    else:
        pomodoro_task_id = None
        pomo_task_label.config(text="未关联任务")

    pomodoro_running = True
    pomo_status.config(text="▶️ 专注中..." if pomodoro_mode == "focus" else "☕ 休息中...")
    status_label.config(text="🍅 番茄钟运行中")

def pause_pomodoro():
    global pomodoro_running
    pomodoro_running = False
    pomo_status.config(text="⏸️ 已暂停")

def reset_pomodoro():
    global pomodoro_running, pomodoro_remaining, pomodoro_mode
    pomodoro_running = False
    pomodoro_mode = "focus"
    try:
        total = int(pomo_focus_var.get()) * 60
    except ValueError:
        total = 25 * 60
    pomodoro_remaining = total
    pomo_time_label.config(text=format_time(pomodoro_remaining))
    pomo_status.config(text="⏹️ 已重置")

def tick_pomodoro():
    global pomodoro_running, pomodoro_remaining, pomodoro_mode
    global pomodoro_task_id

    if pomodoro_running:
        pomodoro_remaining -= 1
        pomo_time_label.config(text=format_time(pomodoro_remaining))

        if pomodoro_remaining <= 0:
            # 切换模式
            if pomodoro_mode == "focus":
                # 完成一个番茄
                if pomodoro_task_id:
                    t = get_task_by_id(pomodoro_task_id)
                    if t:
                        t["pomodoro_count"] = t.get("pomodoro_count", 0) + 1
                        save_data()
                try:
                    break_time = int(pomo_break_var.get()) * 60
                except ValueError:
                    break_time = 5 * 60
                pomodoro_remaining = break_time
                pomodoro_mode = "break"
                pomo_status.config(text="☕ 休息时间!")
                status_label.config(text="☕ 休息一下，喝杯水吧~")
                messagebox.showinfo("🍅 番茄完成!", "专注结束，休息一下吧！")
            else:
                try:
                    focus_time = int(pomo_focus_var.get()) * 60
                except ValueError:
                    focus_time = 25 * 60
                pomodoro_remaining = focus_time
                pomodoro_mode = "focus"
                pomo_status.config(text="▶️ 开始下一个番茄!")
                status_label.config(text="▶️ 休息结束，继续专注！")
                messagebox.showinfo("☕ 休息结束", "准备好开始下一个番茄钟了吗？")

            pomo_time_label.config(text=format_time(pomodoro_remaining))

    root.after(1000, tick_pomodoro)

# ========================
# 绘制任务卡片
# ========================
def draw_task_card(parent, task):
    global selected_task_id

    is_selected = (selected_task_id == task["id"])
    is_done = task.get("done", False)
    prio = task.get("priority", "mid")

    card = tk.Frame(parent, bg=THEME["panel"], relief="solid", bd=1)
    card.pack(fill="x", pady=3, padx=2)

    if is_selected:
        card.configure(bg=THEME["accent_light"], bd=2)

    # 左侧：复选框 + 优先级色条
    left = tk.Frame(card, bg=card["bg"])
    left.pack(side="left", fill="y", padx=(0, 6))

    bar = tk.Frame(left, bg=priority_color(prio), width=4)
    bar.pack(side="left", fill="y")

    cb_var = tk.BooleanVar(value=is_done)
    cb = tk.Checkbutton(left, variable=cb_var, bg=card["bg"],
                         selectcolor=THEME["green_light"],
                         command=lambda: toggle_task(task["id"]))
    cb.pack(side="left", padx=6, pady=8)

    # 中间：信息
    info = tk.Frame(card, bg=card["bg"])
    info.pack(side="left", fill="both", expand=True, pady=4)

    title_text = task["title"]
    if is_done:
        title_text = f"✅ {title_text}"
    else:
        title_text = f"☐ {title_text}"

    title_color = THEME["done"] if is_done else THEME["text"]
    title_font = (FONT_BODY[0], FONT_BODY[1], "overstrike") if is_done else FONT_BODY

    tk.Label(info, text=title_text, font=title_font,
             bg=card["bg"], fg=title_color, anchor="w").pack(anchor="w")

    sub_text = f"{task.get('subject','')}  ⏱ {task.get('duration',0)}分钟  {priority_text(prio)}"
    if task.get("pomodoro_count", 0) > 0:
        sub_text += f"  🍅×{task['pomodoro_count']}"
    tk.Label(info, text=sub_text, font=FONT_SM,
             bg=card["bg"], fg=THEME["text_sec"], anchor="w").pack(anchor="w")

    if task.get("notes", ""):
        tk.Label(info, text=f"📝 {task['notes'][:40]}", font=FONT_SM,
                 bg=card["bg"], fg=THEME["text_sec"], anchor="w").pack(anchor="w")

    # 右侧：按钮
    btn_area = tk.Frame(card, bg=card["bg"])
    btn_area.pack(side="right", padx=4)

    tk.Button(btn_area, text="✏️", font=FONT_SM,
               bg=card["bg"], fg=THEME["text_sec"], relief="flat",
               command=lambda: edit_task(task["id"])).pack(pady=1)
    tk.Button(btn_area, text="📝", font=FONT_SM,
               bg=card["bg"], fg=THEME["text_sec"], relief="flat",
               command=lambda: add_note(task["id"])).pack(pady=1)
    tk.Button(btn_area, text="🗑️", font=FONT_SM,
               bg=card["bg"], fg=THEME["red"], relief="flat",
               command=lambda: delete_task(task["id"])).pack(pady=1)

    # 点击选中
    def select_card(e, tid=task["id"]):
        global selected_task_id
        selected_task_id = tid
        refresh_task_list()

    card.bind("<Button-1>", select_card)
    info.bind("<Button-1>", select_card)

# ========================
# 绘制统计
# ========================
def draw_stats():
    stats_canvas.delete("all")
    today_tasks = get_today_tasks()

    cw = stats_canvas.winfo_width()
    ch = stats_canvas.winfo_height()
    if cw < 10:
        cw = 350
    if ch < 10:
        ch = 200

    pad = 12
    y = pad

    # 总览卡片
    total = len(today_tasks)
    done = sum(1 for t in today_tasks if t.get("done"))
    total_pomo = sum(t.get("pomodoro_count", 0) for t in today_tasks)
    total_min = sum(t.get("duration", 0) for t in today_tasks)

    cards = [
        ("📋 任务", f"{done}/{total}", THEME["accent"]),
        ("⏱ 计划时长", f"{total_min}分钟", THEME["orange"]),
        ("🍅 番茄数", f"{total_pomo}个", THEME["red"]),
    ]

    card_w = (cw - pad * 2 - 8) / 3
    for i, (label, val, color) in enumerate(cards):
        cx = pad + i * (card_w + 4)
        r = stats_canvas.create_rectangle(cx, y, cx + card_w, y + 50,
                                            fill=THEME["accent_light"] if i == 0 else THEME["orange_light"] if i == 1 else THEME["red_light"],
                                            outline="", tags="stat")
        stats_canvas.create_text(cx + card_w / 2, y + 14, text=label,
                                  font=FONT_SM, fill=THEME["text_sec"], tags="stat")
        stats_canvas.create_text(cx + card_w / 2, y + 34, text=val,
                                  font=("Consolas", 14, "bold"), fill=color, tags="stat")

    y += 60

    # 完成率进度条
    tk_label = f"完成率: {int(done/total*100) if total > 0 else 0}%"
    stats_canvas.create_text(pad, y, text=tk_label, font=FONT_SUB,
                              fill=THEME["text"], anchor="w", tags="stat")
    y += 22

    bar_x = pad
    bar_w = cw - pad * 2
    bar_h = 14
    stats_canvas.create_rectangle(bar_x, y, bar_x + bar_w, y + bar_h,
                                    fill=THEME["border"], outline="", tags="stat")
    if total > 0:
        fill_w = bar_w * done / total
        stats_canvas.create_rectangle(bar_x, y, bar_x + fill_w, y + bar_h,
                                        fill=THEME["green"], outline="", tags="stat")
    y += bar_h + 12

    # 科目分布（饼图）
    stats_canvas.create_text(pad, y, text="📊 科目分布", font=FONT_SUB,
                              fill=THEME["text"], anchor="w", tags="stat")
    y += 20

    subj_data = {}
    for t in today_tasks:
        s = t.get("subject", "其他")
        subj_data[s] = subj_data.get(s, 0) + t.get("duration", 0)

    if subj_data:
        pie_cx = cw / 2
        pie_cy = y + 60
        pie_r = 50
        colors = ["#4A6CF7", "#22C55E", "#F59E0B", "#EF4444", "#8B5CF6", "#06B6D4", "#EC4899"]
        total_dur = sum(subj_data.values())
        start_angle = 0
        for i, (s, dur) in enumerate(subj_data.items()):
            extent = dur / total_dur * 360
            color = colors[i % len(colors)]
            stats_canvas.create_arc(pie_cx - pie_r, pie_cy - pie_r,
                                     pie_cx + pie_r, pie_cy + pie_r,
                                     start=start_angle, extent=extent,
                                     fill=color, outline="white", tags="stat")
            start_angle += extent

        # 图例
        ly = y + 5
        lx = pad + 10
        for i, (s, dur) in enumerate(subj_data.items()):
            color = colors[i % len(colors)]
            stats_canvas.create_rectangle(lx, ly, lx + 10, ly + 10,
                                            fill=color, outline="", tags="stat")
            stats_canvas.create_text(lx + 14, ly + 5, text=f"{s} {dur}分",
                                      font=FONT_SM, fill=THEME["text"], anchor="w", tags="stat")
            ly += 16
            if ly > y + 110:
                ly = y + 5
                lx += 120

    y += 130

    # 7日趋势
    stats_canvas.create_text(pad, y, text="📈 7日趋势", font=FONT_SUB,
                              fill=THEME["text"], anchor="w", tags="stat")
    y += 20

    days = []
    for i in range(6, -1, -1):
        d = current_date - datetime.timedelta(days=i)
        days.append(d)

    bar_w2 = (cw - pad * 2) / 7 - 4
    max_val = 1
    day_data = []
    for d in days:
        ds = date_to_str(d)
        day_tasks = [t for t in tasks if t.get("date", "") == ds]
        day_done = sum(1 for t in day_tasks if t.get("done"))
        day_data.append(day_done)
        max_val = max(max_val, day_done)

    chart_h = 60
    for i, (d, val) in enumerate(zip(days, day_data)):
        bx = pad + i * (bar_w2 + 4)
        bh = (val / max_val) * chart_h if max_val > 0 else 0
        color = THEME["accent"] if val > 0 else THEME["border"]
        stats_canvas.create_rectangle(bx, y + chart_h - bh, bx + bar_w2, y + chart_h,
                                        fill=color, outline="", tags="stat")
        stats_canvas.create_text(bx + bar_w2 / 2, y + chart_h + 10,
                                  text=d.strftime("%m/%d"), font=FONT_SM,
                                  fill=THEME["text_sec"], tags="stat")
        if val > 0:
            stats_canvas.create_text(bx + bar_w2 / 2, y + chart_h - bh - 6,
                                      text=str(val), font=FONT_SM,
                                      fill=THEME["text"], tags="stat")

# ========================
# 刷新函数
# ========================
def refresh_task_list():
    for w in task_list_inner.winfo_children():
        w.destroy()

    today_tasks = get_today_tasks()
    today_tasks.sort(key=lambda t: (t.get("done", False), {"high": 0, "mid": 1, "low": 2}.get(t.get("priority", "mid"), 1)))

    if not today_tasks:
        tk.Label(task_list_inner, text="📭 今天还没有任务\n点击上方添加你的第一个任务吧！",
                 font=FONT_BODY, bg=THEME["bg"], fg=THEME["text_sec"],
                 justify="center").pack(pady=20)
    else:
        for t in today_tasks:
            draw_task_card(task_list_inner, t)

    task_canvas.update_idletasks()
    task_canvas.configure(scrollregion=task_canvas.bbox("all"))

def refresh_date_label():
    d = current_date
    weekday_cn = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][d.weekday()]
    date_str = f"{d.year}年{d.month}月{d.day}日 {weekday_cn}"
    date_label.config(text=date_str)
    current_date_label.config(text=date_str)

    # 今天按钮高亮
    if d == datetime.date.today():
        today_btn.config(bg=THEME["accent"], fg="white")
    else:
        today_btn.config(bg=THEME["panel"], fg=THEME["accent"])

def refresh_all():
    refresh_date_label()
    refresh_task_list()
    draw_stats()
    update_status_summary()

def update_status_summary():
    today_tasks = get_today_tasks()
    total = len(today_tasks)
    done = sum(1 for t in today_tasks if t.get("done"))
    total_pomo = sum(t.get("pomodoro_count", 0) for t in today_tasks)

    if total == 0:
        txt = "📭 今天还没有任务，快去添加吧！"
    elif done == total:
        txt = f"🎉 今日任务全部完成！共 {total} 项，🍅 {total_pomo} 个番茄"
    else:
        pct = done / total * 100
        txt = f"📊 进度: {done}/{total} ({pct:.0f}%)  |  🍅 {total_pomo} 个番茄"

    status_label.config(text=txt)

# ========================
# 菜单栏
# ========================
menubar = tk.Menu(root)
root.config(menu=menubar)

file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label="📤 导出今日任务", command=lambda: export_tasks())
file_menu.add_separator()
file_menu.add_command(label="🔄 重置所有数据", command=lambda: reset_all_data())
file_menu.add_separator()
file_menu.add_command(label="❌ 退出", command=root.quit)
menubar.add_cascade(label="📁 文件", menu=file_menu)

help_menu = tk.Menu(menubar, tearoff=0)
help_menu.add_command(label="⌨️ 快捷键说明", command=lambda: show_shortcuts())
help_menu.add_command(label="ℹ️ 关于", command=lambda: show_about())
menubar.add_cascade(label="❓ 帮助", menu=help_menu)

def export_tasks():
    today_tasks = get_today_tasks()
    if not today_tasks:
        messagebox.showinfo("提示", "今天没有任务可导出")
        return
    lines = [f"📅 学习计划 - {date_to_str(current_date)}", "=" * 40]
    for i, t in enumerate(today_tasks, 1):
        status = "✅" if t.get("done") else "⬜"
        lines.append(f"{i}. {status} {t['title']} | {t.get('subject','')} | {t.get('duration',0)}分钟 | {priority_text(t.get('priority','low'))}")
    content = "\n".join(lines)
    try:
        fname = f"study_plan_{date_to_str(current_date)}.txt"
        with open(fname, "w", encoding="utf-8") as f:
            f.write(content)
        messagebox.showinfo("成功", f"已导出到 {fname}")
    except Exception as e:
        messagebox.showerror("错误", str(e))

def reset_all_data():
    if messagebox.askyesno("确认", "确定要清空所有数据吗？此操作不可恢复！"):
        global tasks, selected_task_id
        tasks = []
        selected_task_id = None
        save_data()
        refresh_all()
        status_label.config(text="🔄 数据已重置")

def show_shortcuts():
    msg = """
⌨️ 快捷键说明:

  Enter     - 快速添加任务
  Delete    - 删除选中任务
  Space     - 切换选中任务完成状态
  F2        - 编辑选中任务
  F5        - 刷新界面
  Ctrl+N    - 新建任务
  Ctrl+S    - 导出今日任务
"""
    messagebox.showinfo("快捷键", msg)

def show_about():
    msg = "📅 每日学习计划 v1.0\n\n纯 Python + Tkinter 制作\n无需任何第三方库\n\n祝你学习进步！🎓"
    messagebox.showinfo("关于", msg)

# ========================
# 快捷键绑定
# ========================
def on_enter(e):
    add_task()

def on_delete(e):
    if selected_task_id:
        delete_task(selected_task_id)

def on_space(e):
    if selected_task_id:
        toggle_task(selected_task_id)

def on_f2(e):
    if selected_task_id:
        edit_task(selected_task_id)

def on_f5(e):
    refresh_all()

root.bind("<Return>", on_enter)
root.bind("<Delete>", on_delete)
root.bind("<space>", on_space)
root.bind("<F2>", on_f2)
root.bind("<F5>", on_f5)
root.bind("<Control-n>", lambda e: task_entry.focus_set())
root.bind("<Control-s>", lambda e: export_tasks())

# ========================
# 初始化
# ========================
load_data()

# 如果今天没有任务，添加几个示例
if not get_today_tasks() and current_date == datetime.date.today():
    sample_tasks = [
        {"title": "复习数学第三章", "subject": "📐 数学", "priority": "high", "duration": 45},
        {"title": "背英语单词30个", "subject": "🌍 英语", "priority": "mid", "duration": 20},
        {"title": "完成物理作业", "subject": "🔬 物理", "priority": "high", "duration": 40},
        {"title": "阅读语文课文", "subject": "📖 语文", "priority": "low", "duration": 15},
    ]
    for st in sample_tasks:
        tasks.append({
            "id": gen_id(),
            "title": st["title"],
            "subject": st["subject"],
            "priority": st["priority"],
            "duration": st["duration"],
            "done": False,
            "date": date_to_str(current_date),
            "notes": "",
            "pomodoro_count": 0,
            "created_at": datetime.datetime.now().isoformat(),
        })
    save_data()

refresh_all()
tick_pomodoro()

# ========================
# 启动
# ========================
root.mainloop()
