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

DATA_FILE = "schedule.json"

# 每天节次时间（可按需修改）
PERIODS = [
    ("第1节", "08:00-08:45"),
    ("第2节", "08:55-09:40"),
    ("第3节", "10:00-10:45"),
    ("第4节", "10:55-11:40"),
    ("第5节", "14:00-14:45"),
    ("第6节", "14:55-15:40"),
    ("第7节", "16:00-16:45"),
    ("第8节", "16:55-17:40"),
    ("第9节", "19:00-19:45"),
    ("第10节", "19:55-20:40"),
]

WEEKDAYS = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]

# 课程颜色池（按课程名哈希取色）
COLORS = ["#FFCDD2", "#F8BBD0", "#E1BEE7", "#C5CAE9", "#BBDEFB",
          "#B2EBF2", "#B2DFDB", "#C8E6C9", "#DCEDC8", "#FFF9C4",
          "#FFE0B2", "#FFCCBC", "#D7CCC8", "#CFD8DC"]


def color_for(name):
    return COLORS[sum(ord(c) for c in name) % len(COLORS)]


class ScheduleApp:
    def __init__(self, root):
        self.root = root
        self.root.title("📅 课程表")
        self.root.geometry("980x620")
        self.root.configure(bg="#f5f7fa")

        # 数据结构：{ "1-1": {"name": "...", "teacher": "...", "room": "...", "weeks": "1-16"}, ... }
        # key 为 "周几-第几节"
        self.courses = {}
        self.load_data()

        self.build_ui()
        self.render_grid()

    # ---------- 界面 ----------
    def build_ui(self):
        # 顶部工具栏
        toolbar = tk.Frame(self.root, bg="#f5f7fa")
        toolbar.pack(fill="x", padx=12, pady=8)

        tk.Label(toolbar, text="📅 我的课程表",
                 font=("Microsoft YaHei", 16, "bold"),
                 fg="#1565c0", bg="#f5f7fa").pack(side="left")

        add_btn = tk.Button(toolbar, text="➕ 添加课程", command=self.open_add_dialog,
                            bg="#43a047", fg="white",
                            font=("Microsoft YaHei", 10, "bold"),
                            relief="flat", padx=10, cursor="hand2")
        add_btn.pack(side="right", padx=4)

        del_btn = tk.Button(toolbar, text="🗑 删除选中", command=self.delete_selected,
                            bg="#e53935", fg="white",
                            font=("Microsoft YaHei", 10, "bold"),
                            relief="flat", padx=10, cursor="hand2")
        del_btn.pack(side="right", padx=4)

        clear_btn = tk.Button(toolbar, text="🧹 清空全部", command=self.clear_all,
                              bg="#757575", fg="white",
                              font=("Microsoft YaHei", 10, "bold"),
                              relief="flat", padx=10, cursor="hand2")
        clear_btn.pack(side="right", padx=4)

        # 主体：可滚动的网格区域
        grid_container = tk.Frame(self.root, bg="#f5f7fa")
        grid_container.pack(fill="both", expand=True, padx=12, pady=4)

        self.canvas = tk.Canvas(grid_container, bg="white", highlightthickness=0)
        v_scroll = ttk.Scrollbar(grid_container, orient="vertical",
                                 command=self.canvas.yview)
        h_scroll = ttk.Scrollbar(grid_container, orient="horizontal",
                                 command=self.canvas.xview)
        self.canvas.configure(yscrollcommand=v_scroll.set,
                              xscrollcommand=h_scroll.set)

        self.canvas.grid(row=0, column=0, sticky="nsew")
        v_scroll.grid(row=0, column=1, sticky="ns")
        h_scroll.grid(row=1, column=0, sticky="ew")
        grid_container.rowconfigure(0, weight=1)
        grid_container.columnconfigure(0, weight=1)

        self.grid_frame = tk.Frame(self.canvas, bg="white")
        self.canvas.create_window((0, 0), window=self.grid_frame, anchor="nw")
        self.grid_frame.bind("<Configure>",
                             lambda e: self.canvas.configure(
                                 scrollregion=self.canvas.bbox("all")))

        # 支持鼠标滚轮
        self.canvas.bind_all("<MouseWheel>",
                             lambda e: self.canvas.yview_scroll(int(-e.delta / 120), "units"))

        # 底部状态
        self.status_label = tk.Label(self.root, text="点击「添加课程」开始安排你的课表吧~",
                                     font=("Microsoft YaHei", 9),
                                     fg="#777", bg="#f5f7fa", anchor="w")
        self.status_label.pack(fill="x", padx=14, pady=4)

    # ---------- 渲染网格 ----------
    def render_grid(self):
        # 清空
        for w in self.grid_frame.winfo_children():
            w.destroy()

        CELL_W = 108
        CELL_H = 62
        HEADER_H = 34
        PERIOD_W = 90

        # 左上角
        corner = tk.Label(self.grid_frame, text="节次", bg="#e3f2fd",
                          font=("Microsoft YaHei", 10, "bold"),
                          width=10, height=2, relief="ridge", bd=1)
        corner.grid(row=0, column=0, sticky="nsew")

        # 星期表头
        for j, day in enumerate(WEEKDAYS, start=1):
            lbl = tk.Label(self.grid_frame, text=day, bg="#e3f2fd",
                           font=("Microsoft YaHei", 10, "bold"),
                           relief="ridge", bd=1)
            lbl.grid(row=0, column=j, sticky="nsew")
            self.grid_frame.columnconfigure(j, minsize=CELL_W)
        self.grid_frame.rowconfigure(0, minsize=HEADER_H)

        # 节次行 + 单元格
        for i, (period_name, period_time) in enumerate(PERIODS, start=1):
            # 节次标签
            lbl = tk.Label(self.grid_frame,
                           text=f"{period_name}\n{period_time}",
                           bg="#f1f8e9", font=("Microsoft YaHei", 8),
                           relief="ridge", bd=1, justify="center")
            lbl.grid(row=i, column=0, sticky="nsew")
            self.grid_frame.rowconfigure(i, minsize=CELL_H)

            for j in range(1, 8):
                key = f"{j}-{i}"
                cell = tk.Frame(self.grid_frame, bg="white",
                                relief="ridge", bd=1)
                cell.grid(row=i, column=j, sticky="nsew")

                if key in self.courses:
                    c = self.courses[key]
                    btn = tk.Button(cell,
                                    text=f"{c['name']}\n{c.get('room', '')}",
                                    bg=color_for(c['name']),
                                    font=("Microsoft YaHei", 9, "bold"),
                                    fg="#333", relief="flat",
                                    wraplength=100, justify="center",
                                    cursor="hand2",
                                    command=lambda k=key: self.show_detail(k))
                    btn.pack(fill="both", expand=True, padx=2, pady=2)
                else:
                    plus = tk.Button(cell, text="+", bg="white", fg="#ccc",
                                     font=("Microsoft YaHei", 12),
                                     relief="flat", cursor="hand2",
                                     command=lambda d=j, p=i: self.open_add_dialog(day=d, period=p))
                    plus.pack(fill="both", expand=True)

        # 更新状态
        self.status_label.config(text=f"共 {len(self.courses)} 门课程安排")

    # ---------- 添加/编辑对话框 ----------
    def open_add_dialog(self, day=1, period=1):
        dialog = tk.Toplevel(self.root)
        dialog.title("添加课程")
        dialog.geometry("340x380")
        dialog.configure(bg="#f5f7fa")
        dialog.transient(self.root)
        dialog.grab_set()

        tk.Label(dialog, text="➕ 添加课程", font=("Microsoft YaHei", 14, "bold"),
                 fg="#1565c0", bg="#f5f7fa").pack(pady=10)

        form = tk.Frame(dialog, bg="#f5f7fa")
        form.pack(padx=20, pady=5, fill="x")

        fields = [
            ("课程名称", "name"),
            ("任课老师", "teacher"),
            ("上课地点", "room"),
            ("上课周次", "weeks"),
        ]
        entries = {}
        for idx, (label_text, key) in enumerate(fields):
            tk.Label(form, text=label_text + "：", bg="#f5f7fa",
                     font=("Microsoft YaHei", 10)).grid(row=idx, column=0,
                                                        sticky="e", pady=6, padx=4)
            e = tk.Entry(form, width=20, font=("Microsoft YaHei", 10))
            e.grid(row=idx, column=1, pady=6, padx=4)
            entries[key] = e
        entries["weeks"].insert(0, "1-16")

        # 星期选择
        tk.Label(form, text="星期：", bg="#f5f7fa",
                 font=("Microsoft YaHei", 10)).grid(row=4, column=0,
                                                    sticky="e", pady=6, padx=4)
        day_var = tk.StringVar(value=WEEKDAYS[day - 1])
        ttk.Combobox(form, textvariable=day_var, values=WEEKDAYS,
                     width=17, state="readonly").grid(row=4, column=1, pady=6, padx=4)

        # 节次选择
        tk.Label(form, text="节次：", bg="#f5f7fa",
                 font=("Microsoft YaHei", 10)).grid(row=5, column=0,
                                                    sticky="e", pady=6, padx=4)
        period_var = tk.StringVar(value=PERIODS[period - 1][0])
        ttk.Combobox(form, textvariable=period_var,
                     values=[p[0] for p in PERIODS],
                     width=17, state="readonly").grid(row=5, column=1, pady=6, padx=4)

        def save():
            name = entries["name"].get().strip()
            if not name:
                messagebox.showwarning("提示", "课程名称不能为空！", parent=dialog)
                return

            d_idx = WEEKDAYS.index(day_var.get()) + 1
            p_idx = [p[0] for p in PERIODS].index(period_var.get()) + 1
            key = f"{d_idx}-{p_idx}"

            if key in self.courses:
                if not messagebox.askyesno("提示", "该时段已有课程，是否覆盖？", parent=dialog):
                    return

            self.courses[key] = {
                "name": name,
                "teacher": entries["teacher"].get().strip(),
                "room": entries["room"].get().strip(),
                "weeks": entries["weeks"].get().strip(),
            }
            self.save_data()
            self.render_grid()
            dialog.destroy()

        btn_bar = tk.Frame(dialog, bg="#f5f7fa")
        btn_bar.pack(pady=15)
        tk.Button(btn_bar, text="保存", command=save,
                  bg="#43a047", fg="white", width=10,
                  font=("Microsoft YaHei", 10, "bold"),
                  relief="flat", cursor="hand2").grid(row=0, column=0, padx=6)
        tk.Button(btn_bar, text="取消", command=dialog.destroy,
                  bg="#bdbdbd", fg="white", width=10,
                  font=("Microsoft YaHei", 10, "bold"),
                  relief="flat", cursor="hand2").grid(row=0, column=1, padx=6)

    # ---------- 详情 ----------
    def show_detail(self, key):
        c = self.courses[key]
        d_idx, p_idx = key.split("-")
        day_name = WEEKDAYS[int(d_idx) - 1]
        period_name = PERIODS[int(p_idx) - 1][0]

        msg = (
            f"📚 {c['name']}\n\n"
            f"🗓 时间：{day_name} {period_name}\n"
            f"👨‍🏫 老师：{c.get('teacher') or '未填写'}\n"
            f"📍 地点：{c.get('room') or '未填写'}\n"
            f"📆 周次：{c.get('weeks') or '未填写'}\n\n"
            f"是否删除该课程？"
        )
        if messagebox.askyesno("课程详情", msg):
            del self.courses[key]
            self.save_data()
            self.render_grid()

    # ---------- 删除 ----------
    def delete_selected(self):
        messagebox.showinfo("提示", "点击课表中的课程方块即可查看并删除该课程。")

    def clear_all(self):
        if not self.courses:
            messagebox.showinfo("提示", "课程表已经是空的了。")
            return
        if messagebox.askyesno("确认", "确定要清空所有课程吗？此操作不可恢复。"):
            self.courses = {}
            self.save_data()
            self.render_grid()

    # ---------- 数据 ----------
    def load_data(self):
        if os.path.exists(DATA_FILE):
            try:
                with open(DATA_FILE, "r", encoding="utf-8") as f:
                    self.courses = json.load(f)
            except Exception:
                self.courses = {}

    def save_data(self):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(self.courses, f, ensure_ascii=False, indent=2)


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