import tkinter as tk
import random
import math
import colorsys

# ========================
# 全局配置
# ========================
WIDTH, HEIGHT = 860, 640

# ========================
# 主题
# ========================
THEMES = {
    "🌸 樱花粉": {"bg": "#FFF0F5", "fg": "#C2185B", "panel": "#FCE4EC", "btn": "#F48FB1", "accent": "#E91E63"},
    "💙 天空蓝": {"bg": "#E3F2FD", "fg": "#0D47A1", "panel": "#BBDEFB", "btn": "#42A5F5", "accent": "#1565C0"},
    "💚 抹茶绿": {"bg": "#E8F5E9", "fg": "#1B5E20", "panel": "#C8E6C9", "btn": "#66BB6A", "accent": "#2E7D32"},
    "🧡 蜜桔橙": {"bg": "#FFF3E0", "fg": "#E65100", "panel": "#FFE0B2", "btn": "#FF9800", "accent": "#EF6C00"},
    "💜 梦幻紫": {"bg": "#F3E5F5", "fg": "#4A148C", "panel": "#E1BEE7", "btn": "#AB47BC", "accent": "#7B1FA2"},
    "🌈 糖果色": {"bg": "#FFF9C4", "fg": "#F57F17", "panel": "#FFF59D", "btn": "#FFD54F", "accent": "#FF8F00"},
}
cur_theme = "🌸 樱花粉"

# ========================
# 颜色工具
# ========================
def hex_to_rgb(h):
    h = h.lstrip("#")
    return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))

def rgb_to_hex(rgb):
    return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"

def rgb_to_hsl(rgb):
    r, g, b = [x/255 for x in rgb]
    mx, mn = max(r,g,b), min(r,g,b)
    diff = mx - mn
    l = (mx + mn) / 2
    if diff == 0:
        h = s = 0
    else:
        s = diff / (1 - abs(2*l - 1)) if 0 < l < 1 else 0
        if mx == r: h = (60*((g-b)/diff) + 360) % 360
        elif mx == g: h = (60*((b-r)/diff) + 120) % 360
        else: h = (60*((r-g)/diff) + 240) % 360
    return h, s*100, l*100

def hsl_to_rgb(h, s, l):
    s /= 100; l /= 100
    if s == 0:
        v = int(l*255)
        return (v, v, v)
    h /= 360
    if l < 0.5: q = l*(1+s)
    else: q = l+s-l*s
    p = 2*l-q
    def hue(t):
        if t < 0: t += 1
        if t > 1: t -= 1
        if t < 1/6: return p+(q-p)*6*t
        if t < 1/2: return q
        if t < 2/3: return p+(q-p)*(2/3-t)*6
        return p
    return (int(hue(h+1/3)*255), int(hue(h)*255), int(hue(h-1/3)*255))

def get_brightness(rgb):
    return int(0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2])

def get_text_color(hex_str):
    rgb = hex_to_rgb(hex_str)
    return "#FFFFFF" if get_brightness(rgb) < 128 else "#212121"

def color_distance(rgb1, rgb2):
    return math.sqrt(sum((a-b)**2 for a,b in zip(rgb1, rgb2)))

def luminance(rgb):
    vals = []
    for c in rgb:
        c /= 255
        vals.append(c/12.92 if c <= 0.03928 else ((c+0.055)/1.055)**2.4)
    return 0.2126*vals[0] + 0.7152*vals[1] + 0.0722*vals[2]

def contrast_ratio(rgb1, rgb2):
    l1, l2 = luminance(rgb1), luminance(rgb2)
    if l1 < l2: l1, l2 = l2, l1
    return (l1 + 0.05) / (l2 + 0.05)

# ========================
# 游戏状态
# ========================
game_mode = "challenge"  # challenge / free / quiz
score = 0
streak = 0
best_streak = 0
total_ans = 0
correct_ans = 0
cur_challenge = None
cur_quiz = None
palette_colors = []
selected_color = None
target_colors = []
challenge_type = ""

# ========================
# UI 引用
# ========================
root = None
canvas = None
lbl_score = None
lbl_streak = None
lbl_question = None
lbl_feedback = None
lbl_accuracy = None
lbl_info = None
theme_btns = []
all_widgets = []
palette_buttons = []
target_buttons = []

# ========================
# 颜色生成
# ========================
def random_color():
    return (random.randint(0,255), random.randint(0,255), random.randint(0,255))

def random_harmonious_palette(n=5):
    """生成和谐调色板"""
    h = random.random() * 360
    s = random.randint(40, 90)
    l = random.randint(40, 80)
    palette = []
    scheme = random.choice(["analogous", "monochromatic", "triadic", "split"])
    
    if scheme == "analogous":
        for i in range(n):
            hh = (h + i * 30) % 360
            palette.append(hsl_to_rgb(hh, s, l))
    elif scheme == "monochromatic":
        for i in range(n):
            ll = clamp(l + (i - n//2) * 12, 20, 90)
            palette.append(hsl_to_rgb(h, s, ll))
    elif scheme == "triadic":
        for i in range(n):
            hh = (h + i * 120) % 360
            palette.append(hsl_to_rgb(hh, s, l))
    else:  # split
        offsets = [0, 150, 210, 30, 180]
        for i in range(n):
            hh = (h + offsets[i]) % 360
            palette.append(hsl_to_rgb(hh, s, l))
    
    return [rgb_to_hex(c) for c in palette]

def clamp(v, lo, hi):
    return max(lo, min(hi, v))

# ========================
# 挑战模式
# ========================
def new_challenge():
    """新挑战"""
    global cur_challenge, challenge_type, target_colors, palette_colors
    
    challenge_type = random.choice([
        "find_warmest", "find_coolest", "find_brightest", "find_darkest",
        "find_most_saturated", "find_least_saturated", "find_complementary",
        "find_analogous", "find_triadic", "match_target"
    ])
    
    if challenge_type == "find_warmest":
        palette = [random_color() for _ in range(5)]
        # 确保有一个明显暖色
        warm_idx = random.randint(0, 4)
        palette[warm_idx] = (255, random.randint(50,150), random.randint(0,50))
        target_idx = max(range(5), key=lambda i: palette[i][0] - palette[i][2])
        cur_challenge = {
            "question": "🔥 找出最暖（最红）的颜色",
            "answer": target_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_coolest":
        palette = [random_color() for _ in range(5)]
        cool_idx = random.randint(0, 4)
        palette[cool_idx] = (random.randint(0,50), random.randint(50,150), 255)
        target_idx = max(range(5), key=lambda i: palette[i][2] - palette[i][0])
        cur_challenge = {
            "question": "❄️ 找出最冷（最蓝）的颜色",
            "answer": target_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_brightest":
        palette = [random_color() for _ in range(5)]
        bright_idx = max(range(5), key=lambda i: get_brightness(palette[i]))
        cur_challenge = {
            "question": "💡 找出最亮的颜色",
            "answer": bright_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_darkest":
        palette = [random_color() for _ in range(5)]
        # 避免全亮
        for i in range(5):
            if i != 0:
                palette[i] = (random.randint(100,255), random.randint(100,255), random.randint(100,255))
        palette[0] = (random.randint(10,60), random.randint(10,60), random.randint(10,60))
        dark_idx = min(range(5), key=lambda i: get_brightness(palette[i]))
        cur_challenge = {
            "question": "🌑 找出最暗的颜色",
            "answer": dark_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_most_saturated":
        palette = []
        sat_vals = []
        for _ in range(5):
            c = random_color()
            h, s, l = rgb_to_hsl(c)
            palette.append(c)
            sat_vals.append(s)
        # 确保差距明显
        max_idx = max(range(5), key=lambda i: sat_vals[i])
        cur_challenge = {
            "question": "🎨 找出最鲜艳（饱和度最高）的颜色",
            "answer": max_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_least_saturated":
        palette = []
        sat_vals = []
        for _ in range(5):
            c = (random.randint(80,180), random.randint(80,180), random.randint(80,180))
            h, s, l = rgb_to_hsl(c)
            palette.append(c)
            sat_vals.append(s)
        min_idx = min(range(5), key=lambda i: sat_vals[i])
        cur_challenge = {
            "question": "🌫️ 找出最灰（饱和度最低）的颜色",
            "answer": min_idx,
            "palette": [rgb_to_hex(c) for c in palette]
        }
    
    elif challenge_type == "find_complementary":
        base = random_color()
        base_h, base_s, base_l = rgb_to_hsl(base)
        comp = hsl_to_rgb((base_h + 180) % 360, base_s, base_l)
        palette = [random_color() for _ in range(4)]
        insert = random.randint(0, 4)
        palette.insert(insert, comp)
        cur_challenge = {
            "question": f"🔄 找出与 {rgb_to_hex(base).upper()} 互补的颜色",
            "answer": insert,
            "palette": [rgb_to_hex(c) for c in palette],
            "base_color": rgb_to_hex(base)
        }
    
    elif challenge_type == "find_analogous":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        base = hsl_to_rgb(h, s, l)
        analogs = [(h + 30) % 360, (h - 30) % 360]
        an_colors = [hsl_to_rgb(a, s, l) for a in analogs]
        palette = [random_color() for _ in range(3)]
        insert = random.randint(0, 4)
        palette.insert(insert, an_colors[0])
        insert2 = random.randint(0, 5)
        if insert2 == insert: insert2 = (insert + 1) % 6
        palette.insert(insert2, an_colors[1])
        # 找最邻近
        target = max(range(min(insert, insert2), max(insert, insert2)+1), 
                      key=lambda i: 0 if i in (insert, insert2) else -1)
        cur_challenge = {
            "question": f"🌈 从基色出发，找出最邻近的两个类似色（选第一个）",
            "answer": insert if insert < insert2 else insert2,
            "palette": [rgb_to_hex(c) for c in palette[:5]]
        }
    
    elif challenge_type == "find_triadic":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        tri = [(h + 120) % 360, (h + 240) % 360]
        tri_colors = [hsl_to_rgb(t, s, l) for t in tri]
        palette = [random_color() for _ in range(3)]
        insert = random.randint(0, 4)
        palette.insert(insert, tri_colors[0])
        cur_challenge = {
            "question": "🔺 找出三角配色中的一个",
            "answer": insert,
            "palette": [rgb_to_hex(c) for c in palette[:5]]
        }
    
    else:  # match_target
        target = random_color()
        close = (clamp(target[0] + random.randint(10,30), 0, 255),
                 clamp(target[1] + random.randint(10,30), 0, 255),
                 clamp(target[2] + random.randint(10,30), 0, 255))
        far1 = (255 - target[0], 255 - target[1], 255 - target[2])
        far2 = random_color()
        palette = [random_color(), random_color()]
        insert = random.randint(0, 3)
        palette.insert(insert, close)
        cur_challenge = {
            "question": f"🎯 找出与 {rgb_to_hex(target).upper()} 最接近的颜色",
            "answer": insert,
            "palette": [rgb_to_hex(c) for c in palette],
            "target": rgb_to_hex(target)
        }
    
    palette_colors = cur_challenge["palette"]
    update_challenge_display()

def check_challenge_answer(idx):
    """检查答案"""
    global score, streak, best_streak, total_ans, correct_ans
    total_ans += 1
    if idx == cur_challenge["answer"]:
        score += 10
        streak += 1
        best_streak = max(best_streak, streak)
        correct_ans += 1
        show_feedback("✅ 正确！+10分", "#4CAF50")
    else:
        streak = 0
        show_feedback(f"❌ 不对哦，正确答案是第 {cur_challenge['answer']+1} 个", "#F44336")
    update_stats()
    root.after(1200, new_challenge)

# ========================
# 自由模式
# ========================
def generate_palette(mode):
    """生成调色板"""
    global palette_colors
    if mode == "complementary":
        base = random_color()
        h, s, l = rgb_to_hsl(base)
        comp = hsl_to_rgb((h+180)%360, s, l)
        palette_colors = [rgb_to_hex(base), rgb_to_hex(comp)]
        lbl_info.config(text=f"互补色：色相对立 180°")
    elif mode == "analogous":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        palette_colors = [rgb_to_hex(hsl_to_rgb((h+i*30)%360, s, l)) for i in range(5)]
        lbl_info.config(text=f"邻近色：色相相差 30°")
    elif mode == "triadic":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        palette_colors = [rgb_to_hex(hsl_to_rgb((h+i*120)%360, s, l)) for i in range(3)]
        lbl_info.config(text=f"三角色：色相相差 120°")
    elif mode == "tetradic":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        palette_colors = [rgb_to_hex(hsl_to_rgb((h+i*90)%360, s, l)) for i in range(4)]
        lbl_info.config(text=f"四角色：色相相差 90°")
    elif mode == "split":
        h = random.random() * 360
        s = random.randint(50, 90)
        l = random.randint(40, 70)
        palette_colors = [rgb_to_hex(hsl_to_rgb((h+i)%360, s, l)) for i in [0, 150, 210]]
        lbl_info.config(text=f"分裂互补：主色 + 互补两侧各 30°")
    elif mode == "monochromatic":
        h = random.random() * 360
        s = random.randint(40, 90)
        palette_colors = [rgb_to_hex(hsl_to_rgb(h, s, l)) for l in [25, 40, 55, 70, 85]]
        lbl_info.config(text=f"同色系：同色相不同明度")
    elif mode == "random5":
        palette_colors = [rgb_to_hex(random_color()) for _ in range(5)]
        lbl_info.config(text=f"随机5色组合")
    elif mode == "nature":
        palette = [(34,139,34),(0,100,0),(139,115,85),(218,165,32),(72,209,204)]
        random.shuffle(palette)
        palette_colors = [rgb_to_hex(c) for c in palette]
        lbl_info.config(text=f"自然配色：森林/大地/天空")
    elif mode == "pastel":
        palette = [(255,182,193),(255,218,185),(176,224,230),(221,160,221),(152,251,152)]
        random.shuffle(palette)
        palette_colors = [rgb_to_hex(c) for c in palette]
        lbl_info.config(text=f"粉彩配色：低饱和高明度")
    elif mode == "dark":
        palette = [(30,30,40),(80,20,20),(20,40,60),(50,30,50),(15,15,25)]
        random.shuffle(palette)
        palette_colors = [rgb_to_hex(c) for c in palette]
        lbl_info.config(text=f"暗黑配色：低明度")
    draw_palette()

def draw_palette():
    """绘制调色板"""
    canvas.delete("palette")
    t = THEMES[cur_theme]
    
    if not palette_colors:
        return
    
    n = len(palette_colors)
    cw = (WIDTH - 60) // n
    y = 100
    ch = 120
    
    for i, hex_c in enumerate(palette_colors):
        x = 30 + i * cw
        canvas.create_rectangle(x, y, x+cw-6, y+ch, fill=hex_c, outline="#333", width=2, tags="palette")
        txt = get_text_color(hex_c)
        canvas.create_text(x+cw//2-3, y+ch//2, text=hex_c.upper(), font=("Consolas", 10, "bold"), fill=txt, tags="palette")
        
        # 编号
        canvas.create_text(x+cw//2-3, y+15, text=f"#{i+1}", font=("Comic Sans MS", 10, "bold"), fill=txt, tags="palette")
    
    # 分析
    analyze_palette()

def analyze_palette():
    """分析调色板"""
    if len(palette_colors) < 2:
        return
    
    t = THEMES[cur_theme]
    rgbs = [hex_to_rgb(c) for c in palette_colors]
    
    # 对比度
    min_cr = 999
    pair = (0, 1)
    for i in range(len(rgbs)):
        for j in range(i+1, len(rgbs)):
            cr = contrast_ratio(rgbs[i], rgbs[j])
            if cr < min_cr:
                min_cr = cr
                pair = (i, j)
    
    y = 240
    canvas.create_text(30, y, text=f"📊 调色板分析", font=("Comic Sans MS", 12, "bold"), fill=t["fg"], anchor="w", tags="palette")
    canvas.create_text(30, y+22, text=f"  色数: {len(palette_colors)}", font=("Comic Sans MS", 10), fill=t["fg"], anchor="w", tags="palette")
    canvas.create_text(30, y+42, text=f"  最低对比度: {min_cr:.1f}:1 (色{pair[0]+1} vs 色{pair[1]+1})", font=("Comic Sans MS", 10), fill=t["accent"], anchor="w", tags="palette")
    
    # WCAG
    if min_cr >= 7:
        grade = "✅ AAA 级（优秀）"
    elif min_cr >= 4.5:
        grade = "✅ AA 级（良好）"
    elif min_cr >= 3:
        grade = "⚠️ A 级（可用）"
    else:
        grade = "❌ 对比度不足"
    canvas.create_text(30, y+62, text=f"  可读性: {grade}", font=("Comic Sans MS", 10, "bold"), fill=t["accent"], anchor="w", tags="palette")
    
    # 色温
    warm_count = sum(1 for r,g,b in rgbs if r > b + 20)
    cool_count = sum(1 for r,g,b in rgbs if b > r + 20)
    if warm_count > cool_count:
        temp = f"🔥 偏暖 ({warm_count}暖/{cool_count}冷)"
    elif cool_count > warm_count:
        temp = f"❄️ 偏冷 ({warm_count}暖/{cool_count}冷)"
    else:
        temp = f"⚖️ 中性"
    canvas.create_text(30, y+82, text=f"  色调: {temp}", font=("Comic Sans MS", 10), fill=t["fg"], anchor="w", tags="palette")

# ========================
# 配色测试（小测验）
# ========================
def new_quiz():
    """新测验题"""
    global cur_quiz
    qtypes = [
        "name_hue", "name_saturation", "match_pair", "read_hex", "contrast_test"
    ]
    qtype = random.choice(qtypes)
    
    if qtype == "name_hue":
        colors = [
            ("🔴 红色系", (220, 30, 30)),
            ("🔵 蓝色系", (30, 80, 220)),
            ("🟢 绿色系", (30, 180, 50)),
            ("🟡 黄色系", (240, 220, 30)),
            ("🟣 紫色系", (140, 40, 200)),
            ("🟠 橙色系", (240, 130, 20)),
        ]
        cname, crgb = random.choice(colors)
        # 混入干扰项
        others = [c for c in colors if c[0] != cname]
        distractors = random.sample(others, 3)
        options = [(cname, True)] + [(d[0], False) for d in distractors]
        random.shuffle(options)
        cur_quiz = {
            "question": f"这个颜色属于什么色系？",
            "display": rgb_to_hex(crgb),
            "options": options,
            "type": "choice"
        }
    
    elif qtype == "name_saturation":
        h = random.randint(0, 360)
        s_high = hsl_to_rgb(h, 90, 50)
        s_low = hsl_to_rgb(h, 10, 50)
        cur_quiz = {
            "question": f"哪个颜色更鲜艳（饱和度高）？",
            "display_pair": [rgb_to_hex(s_high), rgb_to_hex(s_low)],
            "options": [("左边", True), ("右边", False)],
            "type": "pair"
        }
    
    elif qtype == "match_pair":
        base = random_color()
        h, s, l = rgb_to_hsl(base)
        comp = hsl_to_rgb((h+180)%360, s, l)
        wrong = random_color()
        cur_quiz = {
            "question": f"哪个是与左侧互补的颜色？",
            "display": rgb_to_hex(base),
            "options": [(rgb_to_hex(comp), True), (rgb_to_hex(wrong), False)],
            "type": "choice"
        }
    
    elif qtype == "read_hex":
        c = random_color()
        hex_c = rgb_to_hex(c)
        # 构造干扰项
        r2 = clamp(c[0]+random.randint(30,80), 0, 255)
        g2 = clamp(c[1]+random.randint(30,80), 0, 255)
        b2 = clamp(c[2]+random.randint(30,80), 0, 255)
        wrong = rgb_to_hex((r2, g2, b2))
        cur_quiz = {
            "question": f"哪个HEX值对应左边这个颜色？",
            "display": hex_c,
            "options": [(hex_c, True), (wrong, False)],
            "type": "choice"
        }
    
    else:  # contrast_test
        fg_c = random_color()
        bg_c = random_color()
        cr = contrast_ratio(fg_c, bg_c)
        is_good = cr >= 4.5
        # 可能反转答案
        if random.random() < 0.3:
            # 降低对比度
            bg_c = (clamp(fg_c[0]+random.randint(-20,20),0,255),
                    clamp(fg_c[1]+random.randint(-20,20),0,255),
                    clamp(fg_c[2]+random.randint(-20,20),0,255))
            cr = contrast_ratio(fg_c, bg_c)
            is_good = cr >= 4.5
        
        cur_quiz = {
            "question": f"这组前景/背景色对比度是否达标(AA级 4.5:1)？",
            "display_pair": [rgb_to_hex(fg_c), rgb_to_hex(bg_c)],
            "options": [("✅ 达标", is_good), ("❌ 不达标", not is_good)],
            "type": "pair",
            "cr": cr
        }
    
    draw_quiz()

def draw_quiz():
    """绘制测验"""
    canvas.delete("quiz")
    t = THEMES[cur_theme]
    
    if not cur_quiz:
        return
    
    y = 350
    canvas.create_rectangle(20, y-10, WIDTH-20, HEIGHT-80, fill=t["panel"], outline=t["accent"], width=2, tags="quiz")
    
    canvas.create_text(WIDTH//2, y+15, text=f"📝 {cur_quiz['question']}", 
                       font=("Comic Sans MS", 13, "bold"), fill=t["fg"], tags="quiz")
    
    if cur_quiz["type"] == "choice":
        # 显示色块
        if "display" in cur_quiz:
            hex_c = cur_quiz["display"]
            canvas.create_rectangle(WIDTH//2-40, y+30, WIDTH//2+40, y+80, fill=hex_c, outline="#333", tags="quiz")
        
        # 选项
        opts = cur_quiz["options"]
        oy = y + 95
        for i, (text, _) in enumerate(opts):
            bx = WIDTH//2 - 120 + i * 240
            btn_id = f"quiz_opt_{i}"
            canvas.create_rectangle(bx, oy, bx+200, oy+30, fill=t["btn"], outline="#333", 
                                    width=2, tags=("quiz", "quiz_btn", btn_id))
            txt_c = get_text_color(t["btn"])
            canvas.create_text(bx+100, oy+15, text=text, font=("Comic Sans MS", 10, "bold"), fill=txt_c, tags=("quiz", btn_id))
    
    elif cur_quiz["type"] == "pair":
        pair = cur_quiz["display_pair"]
        # 左右两个色块
        canvas.create_rectangle(WIDTH//2-160, y+35, WIDTH//2-20, y+95, fill=pair[0], outline="#333", tags="quiz")
        canvas.create_rectangle(WIDTH//2+20, y+35, WIDTH//2+160, y+95, fill=pair[1], outline="#333", tags="quiz")
        canvas.create_text(WIDTH//2-90, y+120, text="← 选项A", font=("Comic Sans MS", 10), fill=t["fg"], tags="quiz")
        canvas.create_text(WIDTH//2+90, y+120, text="选项B →", font=("Comic Sans MS", 10), fill=t["fg"], tags="quiz")
        
        # 选项按钮
        opts = cur_quiz["options"]
        oy = y + 140
        for i, (text, _) in enumerate(opts):
            bx = WIDTH//2 - 100 + i * 200
            canvas.create_rectangle(bx, oy, bx+160, oy+28, fill=t["btn"], outline="#333",
                                    width=2, tags=("quiz", "quiz_btn", f"quiz_opt_{i}"))
            txt_c = get_text_color(t["btn"])
            canvas.create_text(bx+80, oy+14, text=text, font=("Comic Sans MS", 10, "bold"), fill=txt_c, tags=("quiz", f"quiz_opt_{i}"))

def check_quiz_answer(option_idx):
    """检查测验答案"""
    global score, streak, best_streak, total_ans, correct_ans
    
    total_ans += 1
    is_correct = cur_quiz["options"][option_idx][1]
    
    if is_correct:
        score += 5
        streak += 1
        best_streak = max(best_streak, streak)
        correct_ans += 1
        show_feedback("✅ 答对！+5分", "#4CAF50")
    else:
        streak = 0
        show_feedback("❌ 答错了，再想想~", "#F44336")
    
    update_stats()
    root.after(1000, new_quiz)

# ========================
# 反馈
# ========================
def show_feedback(text, color):
    lbl_feedback.config(text=text, fg=color)
    root.after(1500, lambda: lbl_feedback.config(text=""))

# ========================
# 统计
# ========================
def update_stats():
    lbl_score.config(text=f"⭐ 得分: {score}")
    lbl_streak.config(text=f"🔥 连对: {streak} (最高:{best_streak})")
    acc = (correct_ans / total_ans * 100) if total_ans > 0 else 0
    lbl_accuracy.config(text=f"📊 正确率: {acc:.0f}% ({correct_ans}/{total_ans})")

# ========================
# 模式切换
# ========================
def set_mode(mode):
    global game_mode
    game_mode = mode
    canvas.delete("all")
    if mode == "challenge":
        lbl_question.config(text="🎯 挑战模式：从5个颜色中选出符合描述的那个")
        new_challenge()
    elif mode == "free":
        lbl_question.config(text="🎨 自由模式：选择配色方案，分析色彩关系")
        palette_colors = []
        lbl_info.config(text="点击上方按钮生成调色板")
        draw_palette()
    elif mode == "quiz":
        lbl_question.config(text="📝 测验模式：测试你的色彩感知力")
        new_quiz()

# ========================
# 换肤
# ========================
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 game_mode == "free":
        draw_palette()
    elif game_mode == "challenge":
        update_challenge_display()
    elif game_mode == "quiz":
        draw_quiz()

def update_challenge_display():
    """更新挑战显示"""
    if not cur_challenge:
        return
    t = THEMES[cur_theme]
    lbl_question.config(text=f"🎯 {cur_challenge['question']}")
    
    canvas.delete("challenge")
    palette = cur_challenge["palette"]
    n = len(palette)
    cw = (WIDTH - 60) // n
    y = 80
    
    for i, hex_c in enumerate(palette):
        x = 30 + i * cw
        canvas.create_rectangle(x, y, x+cw-6, y+100, fill=hex_c, outline="#333", width=2, tags="challenge")
        txt = get_text_color(hex_c)
        canvas.create_text(x+cw//2-3, y+50, text=hex_c.upper(), font=("Consolas", 10), fill=txt, tags="challenge")
        
        # 点击区域
        btn_id = f"color_opt_{i}"
        canvas.create_rectangle(x, y, x+cw-6, y+100, fill="", outline="", 
                                tags=("challenge", "color_btn", btn_id))
    
    # 提示
    if "base_color" in cur_challenge:
        canvas.create_text(WIDTH//2, y+120, text=f"基色: {cur_challenge['base_color'].upper()}",
                           font=("Comic Sans MS", 11, "bold"), fill=t["accent"], tags="challenge")
    if "target" in cur_challenge:
        canvas.create_text(WIDTH//2, y+120, text=f"目标: {cur_challenge['target'].upper()}",
                           font=("Comic Sans MS", 11, "bold"), fill=t["accent"], tags="challenge")

# ========================
# 画布点击
# ========================
def on_canvas_click(e):
    """处理画布点击"""
    if game_mode == "challenge" and cur_challenge:
        tags = canvas.find_closest(e.x, e.y)
        if tags:
            tag = canvas.gettags(tags[0])
            for t in tag:
                if t.startswith("color_opt_"):
                    idx = int(t.split("_")[-1])
                    check_challenge_answer(idx)
                    return
    
    if game_mode == "quiz" and cur_quiz:
        tags = canvas.find_closest(e.x, e.y)
        if tags:
            tag = canvas.gettags(tags[0])
            for t in tag:
                if t.startswith("quiz_opt_"):
                    idx = int(t.split("_")[-1])
                    check_quiz_answer(idx)
                    return

# ========================
# 构建界面
# ========================
def build_ui():
    global root, canvas, lbl_score, lbl_streak, lbl_question
    global lbl_feedback, lbl_accuracy, lbl_info
    global theme_btns, all_widgets
    
    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", 12, "bold"))
    lbl_score.pack(side="left", padx=10)
    
    lbl_streak = tk.Label(top, text="🔥 连对: 0 (最高:0)", font=("Comic Sans MS", 11))
    lbl_streak.pack(side="left", padx=10)
    
    lbl_accuracy = tk.Label(top, text="📊 正确率: 0%", font=("Comic Sans MS", 11))
    lbl_accuracy.pack(side="left", padx=10)
    
    btn_reset = tk.Button(top, text="🔄 重置", font=("Comic Sans MS", 10),
                           command=lambda: [reset_all(), set_mode(game_mode)])
    btn_reset.pack(side="right", padx=10)
    
    # ====== 主题栏 ======
    tf = tk.Frame(root)
    tf.pack(fill="x", pady=1)
    tk.Label(tf, text="🎨 ", font=("", 8)).pack(side="left", padx=3)
    for name in THEMES:
        btn = tk.Button(tf, 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)
    
    # ====== 模式栏 ======
    mode_bar = tk.Frame(root)
    mode_bar.pack(fill="x", pady=3)
    
    tk.Label(mode_bar, text="📋 模式：", font=("Comic Sans MS", 10, "bold")).pack(side="left", padx=5)
    
    btn_c = tk.Button(mode_bar, text="🎯 挑战模式", font=("Comic Sans MS", 9, "bold"),
                       bg="#E91E63", fg="white", command=lambda: set_mode("challenge"))
    btn_c.pack(side="left", padx=3)
    
    btn_f = tk.Button(mode_bar, text="🎨 自由模式", font=("Comic Sans MS", 9, "bold"),
                       bg="#42A5F5", fg="white", command=lambda: set_mode("free"))
    btn_f.pack(side="left", padx=3)
    
    btn_q = tk.Button(mode_bar, text="📝 测验模式", font=("Comic Sans MS", 9, "bold"),
                       bg="#7B1FA2", fg="white", command=lambda: set_mode("quiz"))
    btn_q.pack(side="left", padx=3)
    
    # 自由模式按钮
    tk.Label(mode_bar, text="  |  配色方案：", font=("Comic Sans MS", 9)).pack(side="left", padx=(10,3))
    schemes = [
        ("互补", "complementary"), ("邻近", "analogous"), ("三角", "triadic"),
        ("四角", "tetradic"), ("分裂", "split"), ("同色", "monochromatic"),
        ("随机", "random5"), ("自然", "nature"), ("粉彩", "pastel"), ("暗黑", "dark")
    ]
    for name, key in schemes:
        btn = tk.Button(mode_bar, text=name, font=("Comic Sans MS", 7),
                         command=lambda k=key: generate_palette(k))
        btn.pack(side="left", padx=1)
    
    # ====== 题目 ======
    q_frame = tk.Frame(root)
    q_frame.pack(fill="x", pady=2)
    
    lbl_question = tk.Label(q_frame, text="", font=("Comic Sans MS", 14, "bold"))
    lbl_question.pack(side="left", padx=15)
    
    lbl_info = tk.Label(q_frame, text="", font=("Comic Sans MS", 10))
    lbl_info.pack(side="left", padx=15)
    
    lbl_feedback = tk.Label(q_frame, text="", font=("Comic Sans MS", 13, "bold"))
    lbl_feedback.pack(side="right", padx=15)
    
    # ====== 画布 ======
    canvas_frame = tk.Frame(root)
    canvas_frame.pack(fill="both", expand=True, padx=3, pady=2)
    
    canvas = tk.Canvas(canvas_frame, width=WIDTH-10, height=400, highlightthickness=0)
    canvas.pack(fill="both", expand=True)
    canvas.bind("<Button-1>", on_canvas_click)
    
    # ====== 底部提示 ======
    bottom = tk.Frame(root)
    bottom.pack(fill="x", side="bottom", pady=2)
    tk.Label(bottom, text="💡 挑战模式：点选颜色 | 测验模式：点选答案 | 自由模式：观察分析",
             font=("Comic Sans MS", 9)).pack()
    
    all_widgets.extend([top, tf, mode_bar, q_frame, canvas_frame, bottom,
                        btn_reset, lbl_score, lbl_streak, lbl_accuracy,
                        lbl_question, lbl_feedback, lbl_info, btn_c, btn_f, btn_q])

# ========================
# 重置
# ========================
def reset_all():
    global score, streak, best_streak, total_ans, correct_ans
    global cur_challenge, cur_quiz, palette_colors
    score = 0
    streak = 0
    best_streak = 0
    total_ans = 0
    correct_ans = 0
    cur_challenge = None
    cur_quiz = None
    palette_colors = []
    update_stats()

# ========================
# 启动
# ========================
def init():
    build_ui()
    apply_theme("🌸 樱花粉")
    reset_all()
    set_mode("challenge")

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