import tkinter as tk
from tkinter import messagebox
import random
import math
import time

# ========================
# 全局配置
# ========================
WIDTH, HEIGHT = 800, 560
TIME_LIMITS = [30, 60, 90, 120, 180]  # 秒
OP_NAMES = {"+": "加法", "-": "减法", "×": "乘法", "÷": "除法", "混合": "混合运算"}

# ========================
# 主题
# ========================
THEMES = {
    "🌸 樱花粉": {"bg": "#FFF0F5", "fg": "#C2185B", "panel": "#FCE4EC", "btn": "#F48FB1", "accent": "#E91E63", "correct": "#4CAF50", "wrong": "#F44336", "card": "#FFF9FC"},
    "💙 天空蓝": {"bg": "#E3F2FD", "fg": "#0D47A1", "panel": "#BBDEFB", "btn": "#42A5F5", "accent": "#1565C0", "correct": "#2E7D32", "wrong": "#D32F2F", "card": "#F0F8FF"},
    "💚 抹茶绿": {"bg": "#E8F5E9", "fg": "#1B5E20", "panel": "#C8E6C9", "btn": "#66BB6A", "accent": "#2E7D32", "correct": "#33691E", "wrong": "#B71C1C", "card": "#F5FFF5"},
    "🧡 蜜桔橙": {"bg": "#FFF3E0", "fg": "#E65100", "panel": "#FFE0B2", "btn": "#FF9800", "accent": "#EF6C00", "correct": "#1B5E20", "wrong": "#C62828", "card": "#FFF8F0"},
    "💜 梦幻紫": {"bg": "#F3E5F5", "fg": "#4A148C", "panel": "#E1BEE7", "btn": "#AB47BC", "accent": "#7B1FA2", "correct": "#2E7D32", "wrong": "#C62828", "card": "#FBF0FF"},
    "🖤 竞技黑": {"bg": "#212121", "fg": "#E0E0E0", "panel": "#424242", "btn": "#616161", "accent": "#FF6F00", "correct": "#00E676", "wrong": "#FF1744", "card": "#303030"},
}
cur_theme = "🌸 樱花粉"

# ========================
# 游戏状态
# ========================
state = {
    "running": False,
    "paused": False,
    "time_left": 60,
    "total_time": 60,
    "score": 0,
    "correct": 0,
    "wrong": 0,
    "combo": 0,
    "max_combo": 0,
    "ops": ["+", "-"],
    "difficulty": "简单",
    "cur_a": 0,
    "cur_b": 0,
    "cur_op": "+",
    "cur_ans": 0,
    "history": [],  # [(q, user_ans, correct, time_taken)]
    "start_ts": 0,
    "q_start": 0,
    "round_count": 0,
}

# ========================
# UI 引用
# ========================
root = None
canvas = None
lbl_score = None
lbl_timer = None
lbl_combo = None
lbl_accuracy = None
lbl_question = None
lbl_feedback = None
lbl_stats = None
entry_ans = None
op_btns = {}
diff_btns = {}
time_btns = {}
theme_btns = []
all_widgets = []

# ========================
# 题目生成
# ========================
def gen_question():
    """生成一道口算题"""
    ops = state["ops"]
    diff = state["difficulty"]
    
    if diff == "简单":
        ranges = {"+": (1, 20), "-": (1, 20), "×": (2, 9), "÷": (2, 9)}
    elif diff == "中等":
        ranges = {"+": (10, 99), "-": (10, 99), "×": (2, 15), "÷": (2, 12)}
    else:  # 困难
        ranges = {"+": (50, 999), "-": (50, 999), "×": (5, 25), "÷": (3, 20)}
    
    op = random.choice(ops)
    lo, hi = ranges.get(op, (1, 20))
    
    if op == "+":
        a = random.randint(lo, hi)
        b = random.randint(lo, hi)
        ans = a + b
    elif op == "-":
        a = random.randint(lo, hi)
        b = random.randint(lo, a)  # 确保不退位太多
        ans = a - b
    elif op == "×":
        a = random.randint(lo, hi)
        b = random.randint(lo, hi)
        ans = a * b
    elif op == "÷":
        b = random.randint(lo, hi)
        ans = random.randint(2, 20)
        a = b * ans  # 确保整除
        ans = a // b
    else:
        a = b = ans = 0
    
    # 减法结果不能为负
    if op == "-" and ans < 0:
        a, b = b, a
        ans = a - b
    
    state["cur_a"] = a
    state["cur_b"] = b
    state["cur_op"] = op
    state["cur_ans"] = ans
    state["q_start"] = time.time()
    
    return f"{a} {op} {b} = ?"

def get_text_color(hex_str, bg_dark=False):
    h = hex_str.lstrip("#")
    try:
        r, g, b = [int(h[i:i+2], 16) for i in (0, 2, 4)]
    except:
        return "#FFFFFF" if bg_dark else "#212121"
    bright = 0.299*r + 0.587*g + 0.114*b
    return "#FFFFFF" if bright < 140 else "#212121"

# ========================
# 游戏控制
# ========================
def start_game():
    """开始/重新开始"""
    state["running"] = True
    state["paused"] = False
    state["time_left"] = state["total_time"]
    state["score"] = 0
    state["correct"] = 0
    state["wrong"] = 0
    state["combo"] = 0
    state["max_combo"] = 0
    state["history"] = []
    state["round_count"] = 0
    state["start_ts"] = time.time()
    
    entry_ans.config(state="normal")
    entry_ans.delete(0, "end")
    entry_ans.focus_set()
    
    q = gen_question()
    lbl_question.config(text=q)
    lbl_feedback.config(text="⏱️ 计时开始！", fg=THEMES[cur_theme]["accent"])
    
    log_msg(f"🚀 开始训练！时长{state['total_time']}秒 | {state['difficulty']} | {', '.join(state['ops'])}")
    update_display()
    game_loop()

def pause_game():
    if not state["running"]:
        return
    state["paused"] = not state["paused"]
    if state["paused"]:
        lbl_feedback.config(text="⏸️ 已暂停", fg=THEMES[cur_theme]["accent"])
        log_msg("⏸️ 已暂停")
    else:
        lbl_feedback.config(text="▶️ 继续！", fg=THEMES[cur_theme]["correct"])
        entry_ans.focus_set()
        log_msg("▶️ 继续")

def end_game():
    """结束游戏，显示结果"""
    state["running"] = False
    entry_ans.config(state="disabled")
    
    total = state["correct"] + state["wrong"]
    acc = (state["correct"] / total * 100) if total > 0 else 0
    
    # 评价
    if acc >= 90 and state["max_combo"] >= 10:
        rank = "🏆 口算大师"
        comment = "太强了！你是人形计算器吗？！"
    elif acc >= 80:
        rank = "🥇 口算高手"
        comment = "非常厉害！继续保持！"
    elif acc >= 60:
        rank = "🥈 口算达人"
        comment = "不错的成绩，再加把劲！"
    elif acc >= 40:
        rank = "🥉 口算新手"
        comment = "还行，多练练会更好！"
    else:
        rank = "💪 继续努力"
        comment = "别灰心，多练习就能进步！"
    
    # 弹窗
    msg = f"{rank}\n\n"
    msg += f"得分: {state['score']}\n"
    msg += f"正确: {state['correct']}\n"
    msg += f"错误: {state['wrong']}\n"
    msg += f"准确率: {acc:.1f}%\n"
    msg += f"最大连击: {state['max_combo']}\n"
    msg += f"总题数: {total}\n\n"
    msg += comment
    
    messagebox.showinfo("⏰ 时间到！", msg)
    log_msg(f"🏁 结束 | {rank} | 得分{state['score']} | 准确率{acc:.0f}%")
    lbl_feedback.config(text=f"🏁 {rank} | 按「开始」再来一局", fg=THEMES[cur_theme]["accent"])
    update_display()

def submit_answer():
    """提交答案"""
    if not state["running"] or state["paused"]:
        return
    
    user_input = entry_ans.get().strip()
    if not user_input:
        return
    
    try:
        user_ans = int(user_input)
    except ValueError:
        lbl_feedback.config(text="⚠️ 请输入数字！", fg=THEMES[cur_theme]["wrong"])
        entry_ans.delete(0, "end")
        return
    
    elapsed = time.time() - state["q_start"]
    correct = (user_ans == state["cur_ans"])
    state["round_count"] += 1
    
    # 记录
    q_str = f"{state['cur_a']} {state['cur_op']} {state['cur_b']}"
    state["history"].append((q_str, user_ans, correct, elapsed))
    
    if correct:
        state["correct"] += 1
        state["combo"] += 1
        state["max_combo"] = max(state["max_combo"], state["combo"])
        
        # 得分 = 基础分 × 连击加成 × 难度加成
        diff_mult = {"简单": 1, "中等": 2, "困难": 3}[state["difficulty"]]
        time_bonus = max(1, int(5 - elapsed))  # 越快分越高
        points = 10 * diff_mult * min(time_bonus, 3)
        state["score"] += points
        
        # 反馈
        speed = "⚡" if elapsed < 1 else ("🚀" if elapsed < 2 else "✅")
        lbl_feedback.config(
            text=f"{speed} 正确！+{points}分 | 用时{elapsed:.1f}秒",
            fg=THEMES[cur_theme]["correct"]
        )
        log_msg(f"✅ {q_str}={state['cur_ans']} ✓ 你答{user_ans} ({elapsed:.1f}s)")
    else:
        state["wrong"] += 1
        state["combo"] = 0
        lbl_feedback.config(
            text=f"❌ 错误！正确答案是 {state['cur_ans']}",
            fg=THEMES[cur_theme]["wrong"]
        )
        log_msg(f"❌ {q_str}={state['cur_ans']} ✗ 你答{user_ans}")
    
    # 下一题
    entry_ans.delete(0, "end")
    q = gen_question()
    lbl_question.config(text=q)
    update_display()

def skip_question():
    """跳过当前题"""
    if not state["running"] or state["paused"]:
        return
    elapsed = time.time() - state["q_start"]
    q_str = f"{state['cur_a']} {state['cur_op']} {state['cur_b']}"
    state["history"].append((q_str, "跳过", False, elapsed))
    state["combo"] = 0
    state["wrong"] += 1
    lbl_feedback.config(text=f"⏭️ 已跳过，答案: {state['cur_ans']}", fg=THEMES[cur_theme]["wrong"])
    log_msg(f"⏭️ 跳过: {q_str}={state['cur_ans']}")
    entry_ans.delete(0, "end")
    q = gen_question()
    lbl_question.config(text=q)
    update_display()

# ========================
# 设置
# ========================
def set_op(op):
    if op == "混合":
        state["ops"] = ["+", "-", "×", "÷"]
    else:
        if op in state["ops"]:
            state["ops"].remove(op)
            if not state["ops"]:
                state["ops"] = ["+"]
        else:
            state["ops"].append(op)
            if len(state["ops"]) > 4:
                state["ops"] = state["ops"][:4]
    
    # 更新按钮样式
    for o, btn in op_btns.items():
        if o == "混合":
            active = set(state["ops"]) == {"+", "-", "×", "÷"}
        else:
            active = o in state["ops"]
        if active:
            btn.config(relief="sunken", bd=3)
        else:
            btn.config(relief="raised", bd=1)
    
    log_msg(f"📝 运算类型: {state['ops']}")

def set_difficulty(d):
    state["difficulty"] = d
    for name, btn in diff_btns.items():
        if name == d:
            btn.config(relief="sunken", bd=3)
        else:
            btn.config(relief="raised", bd=1)
    log_msg(f"📊 难度: {d}")

def set_time(sec):
    state["total_time"] = sec
    for s, btn in time_btns.items():
        if s == sec:
            btn.config(relief="sunken", bd=3)
        else:
            btn.config(relief="raised", bd=1)
    log_msg(f"⏱️ 时长: {sec}秒")

# ========================
# 显示更新
# ========================
def update_display():
    t = state["time_left"]
    m, s = divmod(int(t), 60)
    time_color = "#F44336" if t <= 10 else THEMES[cur_theme]["accent"]
    lbl_timer.config(text=f"⏱️ {m:02d}:{s:02d}", fg=time_color)
    lbl_score.config(text=f"⭐ {state['score']}")
    lbl_combo.config(text=f"🔥 {state['combo']}" if state["combo"] >= 3 else f"💫 {state['combo']}")
    
    total = state["correct"] + state["wrong"]
    acc = (state["correct"] / total * 100) if total > 0 else 0
    lbl_accuracy.config(text=f"🎯 {acc:.0f}% ({state['correct']}/{total})")
    
    # 统计
    lbl_stats.config(text=f"⚡ 最快: {min((h[3] for h in state['history']), default=0):.1f}s | 🔥 最大连击: {state['max_combo']} | 📝 已答: {state['round_count']}")

# ========================
# 主循环
# ========================
def game_loop():
    if not state["running"] or state["paused"]:
        root.after(200, game_loop)
        return
    
    state["time_left"] -= 0.1
    if state["time_left"] <= 0:
        state["time_left"] = 0
        update_display()
        end_game()
        return
    
    update_display()
    
    # 时间紧迫时闪红
    if state["time_left"] <= 5:
        if int(state["time_left"] * 2) % 2 == 0:
            lbl_timer.config(bg=THEMES[cur_theme]["wrong"])
        else:
            lbl_timer.config(bg=THEMES[cur_theme]["panel"])
    
    root.after(100, game_loop)

# ========================
# 日志
# ========================
log_lines = []
def log_msg(msg):
    global log_lines
    ts = time.strftime("%H:%M:%S")
    log_lines.append(f"[{ts}] {msg}")
    if len(log_lines) > 50:
        log_lines.pop(0)
    if lbl_log:
        lbl_log.config(state="normal")
        lbl_log.delete("1.0", "end")
        for line in log_lines[-8:]:
            lbl_log.insert("end", line + "\n")
        lbl_log.see("end")
        lbl_log.config(state="disabled")

# ========================
# 换肤
# ========================
def apply_theme(name):
    global cur_theme
    cur_theme = name
    t = THEMES[name]
    
    root.config(bg=t["bg"])
    for w in all_widgets:
        try:
            w.config(bg=t["bg"], fg=t["fg"])
        except:
            pass
    
    for btn in theme_btns:
        btn.config(bg=t["btn"], fg="white")
    
    # 特殊控件
    if lbl_question:
        lbl_question.config(bg=t["card"], fg=t["fg"])
    if entry_ans:
        entry_ans.config(bg="white", fg="#212121")
    if lbl_feedback:
        lbl_feedback.config(bg=t["panel"])
    if lbl_timer:
        lbl_timer.config(bg=t["panel"])
    
    update_display()

# ========================
# 历史记录查看
# ========================
def show_history():
    if not state["history"]:
        messagebox.showinfo("记录", "还没有答题记录哦~")
        return
    
    dlg = tk.Toplevel(root)
    dlg.title("📋 答题记录")
    dlg.geometry("480x400")
    dlg.transient(root)
    
    t = THEMES[cur_theme]
    dlg.config(bg=t["bg"])
    
    tk.Label(dlg, text="最近答题记录", font=("Comic Sans MS", 12, "bold"),
             bg=t["bg"], fg=t["fg"]).pack(pady=8)
    
    f = tk.Frame(dlg)
    f.pack(fill="both", expand=True, padx=10)
    
    scroll = tk.Scrollbar(f)
    scroll.pack(side="right", fill="y")
    
    txt = tk.Text(f, font=("Consolas", 9), yscrollcommand=scroll.set, height=18)
    txt.pack(fill="both", expand=True)
    scroll.config(command=txt.yview)
    
    for q, ans, correct, elapsed in reversed(state["history"][-50:]):
        mark = "✅" if correct else "❌"
        color = "green" if correct else "red"
        txt.insert("end", f"{mark} {q} = {ans} ({elapsed:.1f}s)\n", (color,))
    
    txt.tag_config("green", foreground="#2E7D32")
    txt.tag_config("red", foreground="#D32F2F")
    txt.config(state="disabled")
    
    tk.Button(dlg, text="关闭", command=dlg.destroy).pack(pady=5)

# ========================
# 构建界面
# ========================
def build_ui():
    global root, canvas, lbl_score, lbl_timer, lbl_combo, lbl_accuracy
    global lbl_question, lbl_feedback, lbl_stats, entry_ans, lbl_log
    
    root = tk.Tk()
    root.title("⚡ 限时口算训练器")
    root.geometry(f"{WIDTH}x{HEIGHT}")
    root.resizable(False, False)
    
    # ====== 顶部栏 ======
    top = tk.Frame(root)
    top.pack(fill="x", pady=3)
    
    lbl_score = tk.Label(top, text="⭐ 0", font=("Comic Sans MS", 14, "bold"))
    lbl_score.pack(side="left", padx=10)
    
    lbl_combo = tk.Label(top, text="💫 0", font=("Comic Sans MS", 12))
    lbl_combo.pack(side="left", padx=8)
    
    lbl_accuracy = tk.Label(top, text="🎯 0%", font=("Comic Sans MS", 11))
    lbl_accuracy.pack(side="left", padx=8)
    
    lbl_timer = tk.Label(top, text="⏱️ 01:00", font=("Comic Sans MS", 16, "bold"))
    lbl_timer.pack(side="right", padx=10)
    
    # ====== 主题栏 ======
    theme_bar = tk.Frame(root)
    theme_bar.pack(fill="x", pady=1)
    tk.Label(theme_bar, text="🎨 ", font=("", 8)).pack(side="left", padx=3)
    for name in THEMES:
        btn = tk.Button(theme_bar, text=name, font=("Comic Sans MS", 7, "bold"),
                         relief="raised", bd=1, padx=3,
                         command=lambda n=name: apply_theme(n))
        btn.pack(side="left", padx=1)
        theme_btns.append(btn)
    
    # ====== 设置栏 ======
    settings = tk.Frame(root)
    settings.pack(fill="x", pady=3)
    
    # 运算类型
    tk.Label(settings, text="运算:", font=("Comic Sans MS", 9, "bold")).pack(side="left", padx=(8,3))
    for op in ["+", "-", "×", "÷", "混合"]:
        btn = tk.Button(settings, text=op, font=("Comic Sans MS", 10, "bold"),
                         width=3, relief="raised", bd=1,
                         command=lambda o=op: set_op(o))
        btn.pack(side="left", padx=1)
        op_btns[op] = btn
    
    # 难度
    tk.Label(settings, text="| 难度:", font=("Comic Sans MS", 9, "bold")).pack(side="left", padx=(10,3))
    for d in ["简单", "中等", "困难"]:
        btn = tk.Button(settings, text=d, font=("Comic Sans MS", 9),
                         relief="raised", bd=1,
                         command=lambda d=d: set_difficulty(d))
        btn.pack(side="left", padx=1)
        diff_btns[d] = btn
    
    # 时间
    tk.Label(settings, text="| 时间:", font=("Comic Sans MS", 9, "bold")).pack(side="left", padx=(10,3))
    for sec in TIME_LIMITS:
        btn = tk.Button(settings, text=f"{sec}s", font=("Comic Sans MS", 8),
                         relief="raised", bd=1,
                         command=lambda s=sec: set_time(s))
        btn.pack(side="left", padx=1)
        time_btns[sec] = btn
    
    # ====== 主区域 ======
    main = tk.Frame(root)
    main.pack(fill="both", expand=True, pady=5)
    
    # 左侧：题目区域
    left = tk.Frame(main)
    left.pack(side="left", fill="both", expand=True, padx=8)
    
    # 题目卡片
    q_frame = tk.Frame(left, relief="ridge", bd=3)
    q_frame.pack(fill="x", pady=8)
    
    lbl_question = tk.Label(q_frame, text="按「开始」按钮开始训练",
                             font=("Comic Sans MS", 28, "bold"),
                             padx=20, pady=15)
    lbl_question.pack(pady=5)
    
    # 输入框
    entry_frame = tk.Frame(left)
    entry_frame.pack(pady=8)
    
    tk.Label(entry_frame, text="你的答案:", font=("Comic Sans MS", 12)).pack(side="left", padx=5)
    entry_ans = tk.Entry(entry_frame, font=("Comic Sans MS", 18, "bold"),
                          width=8, justify="center", state="disabled")
    entry_ans.pack(side="left", padx=5)
    globals()["entry_ans"] = entry_ans
    
    # 按钮行
    btn_row = tk.Frame(left)
    btn_row.pack(pady=8)
    
    btn_start = tk.Button(btn_row, text="🚀 开始", font=("Comic Sans MS", 12, "bold"),
                           bg="#4CAF50", fg="white", padx=15, command=start_game)
    btn_start.pack(side="left", padx=5)
    
    btn_pause = tk.Button(btn_row, text="⏸️ 暂停", font=("Comic Sans MS", 10),
                           bg="#FF9800", fg="white", padx=10, command=pause_game)
    btn_pause.pack(side="left", padx=3)
    
    btn_skip = tk.Button(btn_row, text="⏭️ 跳过", font=("Comic Sans MS", 10),
                           bg="#9E9E9E", fg="white", padx=10, command=skip_question)
    btn_skip.pack(side="left", padx=3)
    
    btn_history = tk.Button(btn_row, text="📋 记录", font=("Comic Sans MS", 10),
                              bg="#7B1FA2", fg="white", padx=10, command=show_history)
    btn_history.pack(side="left", padx=3)
    
    # 反馈
    lbl_feedback = tk.Label(left, text="⚡ 准备好挑战了吗？", font=("Comic Sans MS", 11))
    lbl_feedback.pack(pady=5)
    
    # 统计
    lbl_stats = tk.Label(left, text="⚡ 最快: 0s | 🔥 最大连击: 0 | 📝 已答: 0",
                          font=("Comic Sans MS", 9))
    lbl_stats.pack(pady=2)
    
    # ====== 右侧：排行榜/提示 ======
    right = tk.Frame(main, width=200)
    right.pack(side="right", fill="y", padx=5)
    
    tk.Label(right, text="💡 小贴士", font=("Comic Sans MS", 11, "bold"),
             anchor="w").pack(fill="x", pady=(0,3))
    
    tips = [
        "⚡ 越快答对，得分越高！",
        "🔥 连击不断，分数翻倍！",
        "× 乘法口诀要记牢~",
        "÷ 除法想乘法逆运算",
        "💡 先算个位，再算十位",
        "🎯 准确率比速度更重要",
        "⏭️ 太难的题可以先跳过",
    ]
    for tip in tips:
        tk.Label(right, text=tip, font=("Comic Sans MS", 8),
                 anchor="w", justify="left").pack(fill="x", padx=3, pady=1)
    
    tk.Label(right, text="⌨️ 快捷键", font=("Comic Sans MS", 11, "bold"),
             anchor="w").pack(fill="x", pady=(10,3))
    
    keys = [
        "Enter → 提交答案",
        "Space → 暂停/继续",
        "S → 跳过此题",
        "R → 重新开始",
    ]
    for k in keys:
        tk.Label(right, text=k, font=("Consolas", 8),
                 anchor="w").pack(fill="x", padx=3, pady=1)
    
    # ====== 底部日志 ======
    log_frame = tk.Frame(root)
    log_frame.pack(fill="x", side="bottom", pady=1)
    
    scroll = tk.Scrollbar(log_frame)
    scroll.pack(side="right", fill="y")
    
    lbl_log = tk.Text(log_frame, font=("Consolas", 8), height=4,
                        yscrollcommand=scroll.set)
    lbl_log.pack(fill="both", expand=True, padx=3)
    scroll.config(command=lbl_log.yview)
    lbl_log.config(state="disabled")
    
    # ====== 收集 ======
    all_widgets.extend([top, theme_bar, settings, main, left, right,
                        btn_row, entry_frame, q_frame, log_frame,
                        btn_start, btn_pause, btn_skip, btn_history,
                        lbl_score, lbl_timer, lbl_combo, lbl_accuracy,
                        lbl_question, lbl_feedback, lbl_stats])
    
    # ====== 键盘绑定 ======
    root.bind("<Return>", lambda e: submit_answer())
    root.bind("<space>", lambda e: pause_game())
    root.bind("<s>", lambda e: skip_question())
    root.bind("<r>", lambda e: start_game() if state["running"] or state["score"] > 0 else None)
    root.focus_set()

# ========================
# 初始化
# ========================
def init():
    build_ui()
    apply_theme("🌸 樱花粉")
    
    # 默认选择
    set_op("+")
    set_op("-")
    set_difficulty("简单")
    set_time(60)
    
    log_msg("⚡ 限时口算训练器已就绪")
    log_msg("💡 选择运算类型和难度 → 按「开始」")
    update_display()

if __name__ == "__main__":
    root = None
    init()
    root.mainloop()
