# 极域电子教室控制系统 v3.1.7
# 完整版（包含所有功能模块）
import os
import json
import hashlib
import tkinter as tk
from tkinter import ttk, messagebox, filedialog, simpledialog
import random
import threading
import time
from datetime import datetime
from pathlib import Path
import subprocess
import sys
import webbrowser
import logging
import binascii
from logging.handlers import RotatingFileHandler
import zipfile
import io
from PIL import Image, ImageTk

# ===================== 系统配置 =====================
ADMIN_ACCOUNT = "SYSTEM-HTY"
ADMIN_PASSWORD = "114514"
VERSION = "3.1.7"
LOG_FILE = "jiyu_control.log"
MAX_LOG_SIZE = 5 * 1024 * 1024  # 5MB
BACKUP_COUNT = 3
ASTRUM_EXE = "Astrum For Online Classroom 4.5.1.exe"
MY_PROGRAM_EXE = "my_program.exe"
BILIBILI_URL = "https://space.bilibili.com/3537109889583643"
THEME_DIR = "Themes"

# ===================== 日志系统 =====================
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        RotatingFileHandler(
            LOG_FILE, 
            maxBytes=MAX_LOG_SIZE,
            backupCount=BACKUP_COUNT,
            encoding='utf-8'
        ),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# ===================== 彩色按钮类 =====================
class ColoredButton(tk.Button):
    def __init__(self, parent, text, color, command=None, width=15):
        self.color = color
        self.hover_color = self._adjust_color(color, -20)
        super().__init__(
            parent,
            text=text,
            bg=color,
            fg='white',
            activebackground=self.hover_color,
            activeforeground='white',
            font=('微软雅黑', 10, 'bold'),
            relief='raised',
            borderwidth=2,
            width=width,
            command=command
        )
        self.bind("<Enter>", self._on_enter)
        self.bind("<Leave>", self._on_leave)
    
    def _adjust_color(self, hex_color, offset):
        rgb = tuple(int(hex_color[i+1:i+3], 16) for i in (0, 2, 4))
        adjusted = [max(0, min(255, x + offset)) for x in rgb]
        return f'#{adjusted[0]:02x}{adjusted[1]:02x}{adjusted[2]:02x}'
    
    def _on_enter(self, event):
        self.config(bg=self.hover_color)
    
    def _on_leave(self, event):
        self.config(bg=self.color)

# ===================== 密钥验证系统 =====================
class KeyValidator:
    @staticmethod
    def validate(key):
        if not key or len(key) != 32:
            return False, "密钥长度必须为32字符"
        
        parts = key.split('-')
        if len(parts) != 5:
            return False, "必须包含5段用连字符分隔"
        
        for i in range(4):
            if len(parts[i]) != 5:
                return False, f"第{i+1}段长度必须为5字符"
            for c in parts[i]:
                if not (c.isupper() or c.isdigit()):
                    return False, f"第{i+1}段包含非法字符: {c}"
        
        if len(parts[4]) != 8:
            return False, "第5段长度必须为8字符"
        
        version = parts[4][-3:]
        if version not in ["VIP", "PRO", "BAS"]:
            return False, "最后3位必须是VIP/PRO/BAS"
        
        digit_sum = sum(int(c) for c in key if c.isdigit())
        required_sums = {"VIP": 30, "PRO": 20, "BAS": 10}
        if digit_sum != required_sums[version]:
            return False, f"{version}版密钥数字总和应为{required_sums[version]}(当前{digit_sum})"
        
        return True, version

# ===================== 认证系统 =====================
class AuthSystem:
    def __init__(self):
        self.users_file = self._get_data_path("user_auth_data.json")
        self.current_user = None
        self.user_version = "BAS"
        self._init_user_file()
    
    def _get_data_path(self, filename):
        try:
            if getattr(sys, 'frozen', False):
                base_path = Path(sys.executable).parent
            else:
                base_path = Path(__file__).parent
            
            data_path = base_path / "data" / filename
            data_path.parent.mkdir(parents=True, exist_ok=True)
            return str(data_path)
        except Exception as e:
            logger.error(f"获取数据路径失败: {str(e)}")
            return str(Path(os.environ.get('TEMP', '/tmp')) / filename)

    def _init_user_file(self):
        if not os.path.exists(self.users_file):
            users = {
                '_warning': "这是账户数据库文件，请勿修改或删除！",
                ADMIN_ACCOUNT: {
                    'password': self._hash_password(ADMIN_PASSWORD),
                    'is_admin': True,
                    'version': 'VIP'
                }
            }
            with open(self.users_file, 'w', encoding='utf-8') as f:
                json.dump(users, f, indent=4)
            logger.info("初始化用户数据文件完成")

    def _hash_password(self, password):
        if password == ADMIN_PASSWORD:
            return hashlib.sha256(password.encode()).hexdigest()
        
        salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
        pwdhash = hashlib.pbkdf2_hmac(
            'sha512',
            password.encode('utf-8'),
            salt,
            150000,
            dklen=128
        )
        return (salt + binascii.hexlify(pwdhash)).decode('ascii')

    def _check_password(self, password, hashed_password):
        if password == ADMIN_PASSWORD:
            return hashlib.sha256(password.encode()).hexdigest() == hashed_password
        
        salt = hashed_password[:64].encode('ascii')
        stored_password = hashed_password[64:]
        pwdhash = hashlib.pbkdf2_hmac(
            'sha512',
            password.encode('utf-8'),
            salt,
            150000,
            dklen=128
        )
        return binascii.hexlify(pwdhash).decode('ascii') == stored_password

    def register(self, username, password):
        try:
            if username in ['_warning', ADMIN_ACCOUNT]:
                return False, "无效的用户名"
                
            try:
                with open(self.users_file, 'r', encoding='utf-8') as f:
                    users = json.load(f)
            except (FileNotFoundError, json.JSONDecodeError):
                users = {}
            
            if username in users:
                return False, "用户名已存在"
            
            if len(password) < 6:
                return False, "密码长度至少6位"
            
            users[username] = {
                'password': self._hash_password(password),
                'is_admin': False,
                'version': 'BAS'
            }
            
            with open(self.users_file, 'w', encoding='utf-8') as f:
                json.dump(users, f, indent=4)
            
            return True, "注册成功"
        except Exception as e:
            logger.error(f"注册失败: {str(e)}")
            return False, f"系统错误：{str(e)}"
    
    def login(self, username, password, key=None):
        try:
            with open(self.users_file, 'r', encoding='utf-8') as f:
                users = json.load(f)
        except (FileNotFoundError, json.JSONDecodeError) as e:
            logger.error(f"加载用户数据失败: {str(e)}")
            return False, "账户系统错误，请联系管理员"
        
        if username == ADMIN_ACCOUNT:
            if password == ADMIN_PASSWORD:
                self.current_user = username
                self.user_version = users[username].get('version', 'VIP')
                logger.info(f"管理员登录成功: {username}")
                return True, "管理员登录成功"
            return False, "密码错误"
        
        if username not in users or username == '_warning':
            return False, "用户名不存在"
        
        if not self._check_password(password, users[username]['password']):
            return False, "密码错误"
        
        if key:
            valid, msg = KeyValidator.validate(key)
            if not valid:
                return False, f"密钥无效: {msg}"
            
            _, version = KeyValidator.validate(key)
            users[username]['version'] = version
            with open(self.users_file, 'w', encoding='utf-8') as f:
                json.dump(users, f, indent=4)
        else:
            return False, "需要提供有效密钥"
        
        self.current_user = username
        self.user_version = users[username].get('version', 'BAS')
        logger.info(f"用户登录成功: {username}")
        return True, "登录成功"
    
    def get_current_user(self):
        return self.current_user
    
    def is_admin(self):
        return self.current_user == ADMIN_ACCOUNT
    
    def get_user_version(self):
        return self.user_version
    
    def has_premium_access(self):
        return self.user_version in ['PRO', 'VIP'] or self.is_admin()
    
    def has_vip_access(self):
        return self.user_version == 'VIP' or self.is_admin()

# ===================== 冒险游戏 =====================
class AdventureGame:
    def __init__(self, ui_handler):
        self.ui = ui_handler
        self.player_name = ""
        self.current_level = 1
        self.max_level = 30
        self.inventory = []
        self.score = 0
        self.start_time = 0
        self.end_time = 0
        self.waiting_for_input = False
        self.current_prompt = ""
        self.correct_answer = ""
    
    def start_game(self):
        self.start_time = time.time()
        self.ui._append_game_text("欢迎来到30关冒险游戏！")
        self.ui._append_game_text("请输入你的名字: ")
        self.waiting_for_input = True
        self.current_prompt = "name"
    
    def process_input(self, user_input):
        if self.waiting_for_input:
            if self.current_prompt == "name":
                self.player_name = user_input
                self.ui._append_game_text(f"\n你好, {self.player_name}! 准备好开始冒险了吗?")
                self.ui._append_game_text("你需要通过30个关卡才能完成游戏。每个关卡都有不同的挑战。")
                self.ui._append_game_text("输入'exit'可以随时退出游戏\n")
                self.ui._append_game_text("祝你好运!\n")
                time.sleep(1)
                self.play_level()
            elif self.current_prompt == "answer":
                if user_input.lower() == 'exit':
                    self.ui._append_game_text("\n游戏已退出")
                    self.ui._return_from_game()
                    return
                
                if user_input.lower() == self.correct_answer:
                    self.ui._append_game_text("正确! 你可以继续下一关。")
                    self.score += 10
                    self.current_level += 1
                    if self.current_level <= self.max_level:
                        time.sleep(1)
                        self.play_level()
                    else:
                        self.end_game()
                else:
                    self.ui._append_game_text("错误! 请再试一次。")
                    self.ui._append_game_text(self.current_prompt)
    
    def play_level(self):
        self.ui._append_game_text(f"\n=== 第 {self.current_level} 关 ===")
        
        if self.current_level == 1:
            self.level_1()
        elif self.current_level == 2:
            self.level_2()
        # ... 其他关卡实现 ...
        elif self.current_level == 30:
            self.level_30()
    
    def level_1(self):
        self.ui._append_game_text("第一关: 数学挑战")
        self.ui._append_game_text("回答以下简单的数学问题:")
        a = random.randint(1, 10)
        b = random.randint(1, 10)
        self.current_prompt = f"{a} + {b} = ?"
        self.correct_answer = str(a + b)
        self.ui._append_game_text(self.current_prompt)
        self.waiting_for_input = True
    
    def level_2(self):
        self.ui._append_game_text("第二关: 猜数字")
        self.ui._append_game_text("我想了一个1到10之间的数字，猜猜是多少?")
        self.secret_number = random.randint(1, 10)
        self.current_prompt = "你的猜测(1-10): "
        self.correct_answer = str(self.secret_number)
        self.ui._append_game_text(self.current_prompt)
        self.waiting_for_input = True
    
    def level_30(self):
        self.ui._append_game_text("第三十关: 最终关卡")
        self.ui._append_game_text("输入'完成'来结束游戏")
        self.current_prompt = "你的答案: "
        self.correct_answer = "完成"
        self.ui._append_game_text(self.current_prompt)
        self.waiting_for_input = True
    
    def end_game(self):
        self.end_time = time.time()
        total_time = self.end_time - self.start_time
        minutes = int(total_time // 60)
        seconds = int(total_time % 60)
        
        self.ui._append_game_text("\n=== 游戏结束 ===")
        self.ui._append_game_text(f"恭喜, {self.player_name}! 你成功完成了所有30关!")
        self.ui._append_game_text(f"你的最终得分: {self.score}")
        self.ui._append_game_text(f"总用时: {minutes}分{seconds}秒")
        self.ui._append_game_text("感谢游玩!")
        self.waiting_for_input = False
        self.ui._enable_exit_button()

# ===================== 主控制工具 =====================
class JiyuControlTool:
    def __init__(self, auth_system, return_callback=None):
        self.auth = auth_system
        self.return_callback = return_callback
        self.window = tk.Tk()
        self.window.title(f"极域控制工具 v{VERSION} - {'管理员版' if self.auth.is_admin() else '普通用户版'}")
        self.window.geometry("800x600")
        self.window.minsize(600, 400)

        
        
        
        self.style = ttk.Style()
        self.style.theme_use('classic')
        self.window.tk.call('tk', 'scaling', 0.95)
        
        self.theme_dir = Path(THEME_DIR)
        self.theme_dir.mkdir(exist_ok=True)
        
        self.theme_image = None
        self.theme_image_label = None
        
        self._create_menu()
        self._create_main_frame()
        self._create_status_bar()
        
        self.window.protocol("WM_DELETE_WINDOW", self._on_close)
    
    def _create_menu(self):
        menubar = tk.Menu(self.window)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label="导入主题包(.zip)", command=self._import_theme_package)
        file_menu.add_command(label="调整窗口大小", command=self._adjust_window_size)
        file_menu.add_command(label="强制置顶", command=self._toggle_always_on_top)
        file_menu.add_separator()
        if self.return_callback:
            file_menu.add_command(label="返回主菜单", command=self._return_to_main)
        file_menu.add_command(label="退出", command=self.window.destroy)
        menubar.add_cascade(label="文件", menu=file_menu)
        
        # 工具菜单
        tool_menu = tk.Menu(menubar, tearoff=0)
        tool_menu.add_command(label="网络破解", command=self._network_crack)
        if self.auth.is_admin():
            tool_menu.add_command(label="密钥工具", command=self._open_key_tools)
        if self.auth.is_admin() or self.auth.has_vip_access():
            tool_menu.add_command(label="高级控制程序", command=self._run_astrum_program)
        menubar.add_cascade(label="工具", menu=tool_menu)
        
        # 游戏菜单
        game_menu = tk.Menu(menubar, tearoff=0)
        game_menu.add_command(label="冒险游戏", command=self._start_adventure_game)
        if self.auth.is_admin() or self.auth.has_premium_access():
            game_menu.add_command(label="数字猜谜", command=self._start_number_guessing_game)
        if self.auth.is_admin() or self.auth.has_vip_access():
            game_menu.add_command(label="记忆游戏", command=self._start_memory_game)
        menubar.add_cascade(label="小游戏", menu=game_menu)
        
        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        help_menu.add_command(label="关于", command=self._show_about)
        menubar.add_cascade(label="帮助", menu=help_menu)
        
        self.window.config(menu=menubar)
    
    def _create_main_frame(self):
        main_frame = ttk.Frame(self.window, padding=15)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        self.notebook = ttk.Notebook(main_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True)
        
        self.control_frame = tk.Frame(self.notebook)
        self.notebook.add(self.control_frame, text="控制工具")
        self._create_control_tab()
        
        self.game_frame = tk.Frame(self.notebook)
        self.notebook.add(self.game_frame, text="小游戏")
        self._create_game_tab()
    
    def _create_control_tab(self):
        title_frame = tk.Frame(self.control_frame, bg='white')
        title_frame.pack(fill=tk.X, pady=10)
        
        tk.Label(
            title_frame,
            text="极域电子教室控制工具",
            font=("微软雅黑", 16, "bold"),
            bg='white'
        ).pack(side=tk.LEFT)
        
        user_frame = tk.Frame(title_frame, bg='white')
        user_frame.pack(side=tk.RIGHT)
        
        tk.Label(
            user_frame,
            text=f"用户: {self.auth.get_current_user()}",
            bg='white'
        ).pack(side=tk.LEFT)
        
        version_color = '#0078d7' if self.auth.get_user_version() == 'BAS' else \
                       '#107c10' if self.auth.get_user_version() == 'PRO' else \
                       '#68217a'
        version_text = '(普通版)' if self.auth.get_user_version() == 'BAS' else \
                      '(豪华版)' if self.auth.get_user_version() == 'PRO' else \
                      '(至尊版)'
        
        tk.Label(
            user_frame,
            text=version_text,
            fg='white',
            bg=version_color,
            font=('微软雅黑', 9, 'bold'),
            padx=5
        ).pack(side=tk.LEFT, padx=5)
        
        if self.auth.is_admin():
            tk.Label(
                user_frame,
                text="(管理员)",
                fg='white',
                bg='red',
                font=('微软雅黑', 9,'bold'),
                padx=5
            ).pack(side=tk.LEFT, padx=5)

        btn_frame = tk.Frame(self.control_frame, bg='white')
        btn_frame.pack(pady=20)
        
        buttons = [
            ("启动控制程序", self._run_my_program, '#0078d7'),
            ("执行网络破解", self._network_crack, '#107c10'),
            ("断网大法！", self._toggle_network, '#d83b01'),
            ("密钥工具", self._open_key_tools, '#ff8c00'),
            ("高级控制程序", self._run_astrum_program, '#68217a')
        ]
        
        for text, command, color in buttons:
            btn = ColoredButton(
                btn_frame,
                text=text,
                color=color,
                command=command,
                width=18
            )
            btn.pack(pady=8, padx=5, ipady=4)
            
            if text == "密钥工具" and not self.auth.is_admin():
                btn.config(state=tk.DISABLED, bg='#cccccc')
            elif text == "高级控制程序" and not (self.auth.is_admin() or self.auth.has_vip_access()):
                btn.config(state=tk.DISABLED, bg='#cccccc')
    
    def _create_game_tab(self):
        game_select_frame = tk.Frame(self.game_frame)
        game_select_frame.pack(fill=tk.X, pady=10)
        
        tk.Label(
            game_select_frame,
            text="选择游戏:",
            font=("微软雅黑", 12)
        ).pack(side=tk.LEFT, padx=5)
        
        adventure_btn = ColoredButton(
            game_select_frame,
            text="30关冒险游戏",
            color='#0078d7',
            command=self._start_adventure_game,
            width=15
        )
        adventure_btn.pack(side=tk.LEFT, padx=5)
        
        guess_btn = ColoredButton(
            game_select_frame,
            text="数字猜谜",
            color='#107c10',
            command=self._start_number_guessing_game,
            width=15
        )
        guess_btn.pack(side=tk.LEFT, padx=5)
        if not (self.auth.is_admin() or self.auth.has_premium_access()):
            guess_btn.config(state=tk.DISABLED, bg='#cccccc')
        
        memory_btn = ColoredButton(
            game_select_frame,
            text="记忆游戏",
            color='#68217a',
            command=self._start_memory_game,
            width=15
        )
        memory_btn.pack(side=tk.LEFT, padx=5)
        if not (self.auth.is_admin() or self.auth.has_vip_access()):
            memory_btn.config(state=tk.DISABLED, bg='#cccccc')
        
        game_display_frame = tk.Frame(self.game_frame)
        game_display_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        self.game_text = tk.Text(
            game_display_frame,
            height=15,
            wrap=tk.WORD,
            font=("Consolas", 12),
            state=tk.DISABLED
        )
        self.game_text.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
        
        scrollbar = tk.Scrollbar(game_display_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.game_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.game_text.yview)
        
        game_input_frame = tk.Frame(self.game_frame)
        game_input_frame.pack(fill=tk.X, padx=10, pady=5)
        
        self.game_input = tk.Entry(
            game_input_frame,
            font=("Consolas", 12)
        )
        self.game_input.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.game_input.bind("<Return>", self._handle_game_input)
        
        submit_btn = tk.Button(
            game_input_frame,
            text="提交",
            command=self._handle_game_input
        )
        submit_btn.pack(side=tk.LEFT, padx=5)
        
        exit_btn = tk.Button(
            game_input_frame,
            text="退出游戏",
            command=self._exit_current_game
        )
        exit_btn.pack(side=tk.LEFT, padx=5)
        
        self.current_game = None
        self.game_active = False
    
    def _create_status_bar(self):
        self.status_var = tk.StringVar()
        self.status_var.set("就绪 | 显示模式: Windows 7 | 字体大小: 9pt")
        
        status_bar = tk.Frame(self.window, bd=1, relief="sunken")
        status_bar.pack(fill=tk.X, padx=5, pady=5)
        
        tk.Label(
            status_bar,
            textvariable=self.status_var,
            font=("微软雅黑", 9),
            anchor="w"
        ).pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        adjust_frame = tk.Frame(status_bar)
        adjust_frame.pack(side=tk.RIGHT, padx=5)
        
        tk.Label(adjust_frame, text="字体:").pack(side=tk.LEFT)
        self.font_size = tk.IntVar(value=9)
        ttk.Combobox(
            adjust_frame, 
            textvariable=self.font_size,
            values=[8, 9, 10, 11, 12, 14, 16],
            width=4,
            state="readonly"
        ).pack(side=tk.LEFT, padx=2)
        
        ttk.Button(
            adjust_frame,
            text="应用",
            command=self._apply_font_size,
            width=4
        ).pack(side=tk.LEFT, padx=2)
        
        tk.Label(adjust_frame, text="模式:").pack(side=tk.LEFT, padx=(10,2))
        self.win_mode = tk.StringVar(value="win7")
        ttk.Combobox(
            adjust_frame, 
            textvariable=self.win_mode,
            values=["win7", "win10", "win11"],
            width=5,
            state="readonly"
        ).pack(side=tk.LEFT, padx=2)
        
        ttk.Button(
            adjust_frame,
            text="应用",
            command=self._apply_win_mode,
            width=4
        ).pack(side=tk.LEFT, padx=2)
    
    def _import_theme_package(self):
        try:
            self.theme_dir.mkdir(exist_ok=True)
            
            file_path = filedialog.askopenfilename(
                title="选择主题包(.zip)",
                filetypes=[("ZIP压缩包", "*.zip"), ("所有文件", "*.*")]
            )
            
            if not file_path:
                return
                
            with zipfile.ZipFile(file_path, 'r') as zip_ref:
                json_files = [f for f in zip_ref.namelist() if f.lower().endswith('.json')]
                
                if not json_files:
                    messagebox.showerror("错误", "ZIP文件中未找到JSON配置文件")
                    return
                    
                with zip_ref.open(json_files[0]) as json_file:
                    with io.TextIOWrapper(json_file, encoding='utf-8') as text_file:
                        try:
                            theme_config = json.load(text_file)
                            
                            info_msg = f"""主题名称: {theme_config.get('theme_name', '未知')}
版本: {theme_config.get('version', '1.0')}
作者: {theme_config.get('author', '未知')}
描述: {theme_config.get('description', '无')}"""
                            
                            messagebox.showinfo("主题信息", info_msg)
                            
                            zip_ref.extractall(self.theme_dir)
                            logger.info(f"主题文件已解压到: {self.theme_dir}")
                            
                            self._apply_theme(theme_config)
                            
                        except json.JSONDecodeError as e:
                            messagebox.showerror("错误", f"JSON解析失败: {str(e)}")
                        except Exception as e:
                            messagebox.showerror("错误", f"处理主题文件失败: {str(e)}")
                            
        except zipfile.BadZipFile:
            messagebox.showerror("错误", "无效的ZIP文件")
        except Exception as e:
            messagebox.showerror("错误", f"导入主题失败: {str(e)}")
    
    def _apply_theme(self, theme_config):
        try:
            if 'window_bg' in theme_config:
                self.window.config(bg=theme_config['window_bg'])
            
            if 'button_style' in theme_config:
                style = theme_config['button_style']
                self.style.configure('TButton', 
                                   foreground=style.get('foreground', 'white'),
                                   background=style.get('background', '#39c5bb'),
                                   font=style.get('font', ('微软雅黑', 10, 'bold')))
            
            if 'text_color' in theme_config:
                for widget in self.window.winfo_children():
                    if isinstance(widget, (tk.Label, tk.Button)):
                        widget.config(fg=theme_config['text_color'])
            
            if 'image_settings' in theme_config:
                self._apply_theme_image(theme_config['image_settings'])
            
            messagebox.showinfo("成功", f"{theme_config.get('theme_name', '主题')}已应用成功!")
            logger.info(f"已应用主题: {theme_config.get('theme_name', '未知')}")
            
        except Exception as e:
            messagebox.showerror("错误", f"应用主题失败: {str(e)}")
            logger.error(f"应用主题失败: {str(e)}")
    
    def _apply_theme_image(self, image_settings):
        try:
            image_file = image_settings.get('file')
            if not image_file:
                return
                
            image_path = self.theme_dir / image_file
            if not image_path.exists():
                messagebox.showwarning("警告", f"找不到图片文件: {image_file}")
                return
                
            img = Image.open(image_path)
            
            transparency = image_settings.get('transparency', 100)
            if transparency < 100:
                img = img.convert("RGBA")
                data = img.getdata()
                new_data = []
                for item in data:
                    new_data.append((item[0], item[1], item[2], int(item[3] * transparency / 100)))
                img.putdata(new_data)
            
            size = image_settings.get('size', 'auto')
            if size != 'auto':
                if isinstance(size, list) and len(size) == 2:
                    img = img.resize((size[0], size[1]), Image.ANTIALIAS)
            
            theme_img = ImageTk.PhotoImage(img)
            
            if hasattr(self, 'theme_image_label'):
                self.theme_image_label.destroy()
            
            self.theme_image_label = tk.Label(self.window, image=theme_img, bg=self.window['bg'])
            self.theme_image_label.image = theme_img
            
            position = image_settings.get('position', 'center')
            if position == 'left':
                self.theme_image_label.pack(side='left', padx=10, pady=10)
            elif position == 'right':
                self.theme_image_label.pack(side='right', padx=10, pady=10)
            elif position == 'top':
                self.theme_image_label.pack(side='top', padx=10, pady=10)
            elif position == 'bottom':
                self.theme_image_label.pack(side='bottom', padx=10, pady=10)
            else:
                self.theme_image_label.place(relx=0.5, rely=0.5, anchor='center')
            
            logger.info(f"已应用主题图片: {image_file} (位置: {position}, 透明度: {transparency}%)")
            
        except ImportError:
            messagebox.showwarning("警告", "未安装Pillow库，无法处理图片")
        except Exception as e:
            messagebox.showerror("错误", f"应用主题图片失败: {str(e)}")
            logger.error(f"应用主题图片失败: {str(e)}")

    def _start_adventure_game(self):
        if self.game_active:
            return
        
        self.game_active = True
        self.current_game = "adventure"
        self.adventure_game = AdventureGame(self)
        
        self.game_text.config(state=tk.NORMAL)
        self.game_text.delete(1.0, tk.END)
        self.game_text.config(state=tk.DISABLED)
        
        self.adventure_game.start_game()
        self.notebook.select(self.game_frame)

    def _start_number_guessing_game(self):
        if self.game_active:
            return
        
        if not (self.auth.is_admin() or self.auth.has_premium_access()):
            messagebox.showinfo("提示", "请升级至豪华版后再尝试！")
            return
        
        self.game_active = True
        self.current_game = "number_guessing"
        self.secret_number = random.randint(1, 100)
        self.guess_count = 0
        
        self.game_text.config(state=tk.NORMAL)
        self.game_text.delete(1.0, tk.END)
        self.game_text.insert(tk.END, "数字猜谜游戏\n")
        self.game_text.insert(tk.END, "我已经想了一个1到100之间的数字，猜猜是多少？\n")
        self.game_text.insert(tk.END, "输入'exit'可以退出游戏\n")
        self.game_text.insert(tk.END, "你的猜测: ")
        self.game_text.config(state=tk.DISABLED)
        
        self.notebook.select(self.game_frame)
        self.game_input.focus()

    def _start_memory_game(self):
        if self.game_active:
            return
        
        if not (self.auth.is_admin() or self.auth.has_vip_access()):
            messagebox.showinfo("提示", "请升级至至尊版后再尝试！")
            return
        
        self.game_active = True
        self.current_game = "memory"
        self.sequence = [random.choice(['红', '绿', '蓝', '黄']) for _ in range(4)]
        self.current_round = 1
        
        self.game_text.config(state=tk.NORMAL)
        self.game_text.delete(1.0, tk.END)
        self.game_text.insert(tk.END, "记忆游戏\n")
        self.game_text.insert(tk.END, "记住以下颜色序列:\n")
        self.game_text.insert(tk.END, " ".join(self.sequence) + "\n")
        self.game_text.insert(tk.END, "(3秒后颜色将消失)\n")
        self.game_text.config(state=tk.DISABLED)
        
        self.notebook.select(self.game_frame)
        self.game_input.focus()
        
        self.window.after(3000, self._hide_memory_sequence)

    def _hide_memory_sequence(self):
        if not self.game_active or self.current_game != "memory":
            return
        
        self.game_text.config(state=tk.NORMAL)
        self.game_text.delete(1.0, tk.END)
        self.game_text.insert(tk.END, "记忆游戏\n")
        self.game_text.insert(tk.END, "输入你记住的颜色序列(用空格分隔): ")
        self.game_text.config(state=tk.DISABLED)

    def _handle_game_input(self, event=None):
        if not self.game_active:
            return
        
        user_input = self.game_input.get().strip()
        self.game_input.delete(0, tk.END)
        
        if user_input.lower() == 'exit':
            self._exit_current_game()
            return
        
        if self.current_game == "adventure":
            self.adventure_game.process_input(user_input)
        elif self.current_game == "number_guessing":
            self._process_number_guess(user_input)
        elif self.current_game == "memory":
            self._process_memory_input(user_input)

    def _process_number_guess(self, guess):
        try:
            guess_num = int(guess)
            self.guess_count += 1
            
            if guess_num < 1 or guess_num > 100:
                self._append_game_text("请输入1到100之间的数字")
                return
            
            if guess_num < self.secret_number:
                self._append_game_text(f"太小了! 你已经猜了{self.guess_count}次")
            elif guess_num > self.secret_number:
                self._append_game_text(f"太大了! 你已经猜了{self.guess_count}次")
            else:
                self._append_game_text(f"恭喜! 你猜对了! 用了{self.guess_count}次")
                self.game_active = False
        except ValueError:
            self._append_game_text("请输入有效的数字")

    def _process_memory_input(self, user_input):
        user_sequence = user_input.split()
        
        if len(user_sequence) != len(self.sequence):
            self._append_game_text(f"错误! 需要输入{len(self.sequence)}个颜色")
            return
        
        correct = True
        for i in range(len(self.sequence)):
            if user_sequence[i] != self.sequence[i]:
                correct = False
                break
        
        if correct:
            self._append_game_text(f"第{self.current_round}轮正确!")
            self.current_round += 1
            if self.current_round > 3:
                self._append_game_text("恭喜! 你完成了所有3轮记忆挑战!")
                self.game_active = False
            else:
                self._start_memory_round()
        else:
            self._append_game_text("错误! 正确的序列是: " + " ".join(self.sequence))
            self.game_active = False

    def _start_memory_round(self):
        self.sequence = [random.choice(['红', '绿', '蓝', '黄']) for _ in range(3 + self.current_round)]
        
        self.game_text.config(state=tk.NORMAL)
        self.game_text.delete(1.0, tk.END)
        self.game_text.insert(tk.END, f"记忆游戏 - 第{self.current_round}轮\n")
        self.game_text.insert(tk.END, "记住以下颜色序列:\n")
        self.game_text.insert(tk.END, " ".join(self.sequence) + "\n")
        self.game_text.insert(tk.END, "(3秒后颜色将消失)\n")
        self.game_text.config(state=tk.DISABLED)
        
        self.window.after(3000, self._hide_memory_sequence)

    def _append_game_text(self, text):
        self.game_text.config(state=tk.NORMAL)
        self.game_text.insert(tk.END, text + "\n")
        self.game_text.see(tk.END)
        self.game_text.config(state=tk.DISABLED)

    def _exit_current_game(self):
        if self.game_active:
            self.game_active = False
            self.current_game = None
            self._append_game_text("游戏已退出")

    def _run_my_program(self):
        if not (self.auth.is_admin() or self.auth.has_premium_access()):
            messagebox.showinfo("提示", "请升级至豪华版后再尝试！")
            return
            
        try:
            self._log("正在启动控制程序...")
            self.status_var.set("正在启动控制程序...")
            
            base_path = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path(__file__).parent
            exe_path = base_path / MY_PROGRAM_EXE
            
            if not exe_path.exists():
                raise FileNotFoundError(f"找不到程序文件: {exe_path}")
            
            self._program_process = subprocess.Popen(str(exe_path))
            self._log(f"已启动控制程序: {MY_PROGRAM_EXE}")
            self.status_var.set("控制程序运行中")
            
        except Exception as e:
            self._log(f"启动失败: {str(e)}")
            self.status_var.set("启动控制程序失败")
            messagebox.showerror("错误", f"无法启动控制程序:\n{str(e)}")
    
    def _network_crack(self):
        if not (self.auth.is_admin() or self.auth.has_vip_access()):
            messagebox.showinfo("提示", "请升级至至尊版后再尝试！")
            return
            
        try:
            confirm = messagebox.askyesno("确认", "执行网络破解可能会影响系统稳定性，确定继续吗？")
            if not confirm:
                return
                
            self._log("正在安全地执行网络破解命令...")
            self.status_var.set("正在安全破解网络限制...")
            
            commands = [
                "taskkill /f /im StudentMain.exe",
                "taskkill /f /im GATESRV.exe",
                "taskkill /f /im MasterHelper.exe",
                "sc stop TDNetFilter"
            ]
            
            for cmd in commands:
                try:
                    subprocess.run(cmd, shell=True, check=True, timeout=5)
                    self._log(f"执行成功: {cmd}")
                except subprocess.TimeoutExpired:
                    self._log(f"命令超时: {cmd}")
                except subprocess.CalledProcessError as e:
                    self._log(f"执行失败: {cmd} (错误: {e.returncode})")
            
            self._log("网络破解命令执行完毕")
            self.status_var.set("破解完成")
            
        except Exception as e:
            self._log(f"网络破解失败: {str(e)}")
            self.status_var.set("破解失败")
            messagebox.showerror("错误", f"执行网络破解时出错:\n{str(e)}")
    
    def _toggle_network(self):
        try:
            if not self.network_disabled:
                confirm = messagebox.askyesno("确认", "断开网络连接可能会影响其他程序，确定继续吗？")
                if not confirm:
                    return
                    
                self._log("正在执行断网操作...")
                self.status_var.set("正在断开网络...")
                
                bat_content = """@echo off
chcp 65001
title 断网大法
color 0c
echo 正在禁用网络适配器...

for /f "tokens=3 delims=: " %%i in ('netsh interface show interface ^| find "已连接"') do (
    netsh interface set interface name="%%i" admin=disabled
    echo 已禁用适配器: %%i
)

echo 断网命令已执行
pause
exit"""
                
                temp_bat = Path(os.environ['TEMP']) / "disable_network.bat"
                with open(temp_bat, 'w', encoding='utf-8') as f:
                    f.write(bat_content)
                
                self._network_process = subprocess.Popen(['cmd', '/c', 'start', 'cmd', '/k', str(temp_bat)], shell=True)
                
                self.network_disabled = True
                self._log("已执行断网命令")
                self.status_var.set("网络已断开")
            else:
                self._log("正在恢复网络连接...")
                self.status_var.set("正在恢复网络...")
                
                bat_content = """@echo off
chcp 65001
title 恢复网络
color 0a
echo 正在启用网络适配器...

for /f "tokens=3 delims=: " %%i in ('netsh interface show interface ^| find "已禁用"') do (
    netsh interface set interface name="%%i" admin=enabled
    echo 已启用适配器: %%i
)

echo 网络恢复命令已执行
pause
exit"""
                
                temp_bat = Path(os.environ['TEMP']) / "enable_network.bat"
                with open(temp_bat, 'w', encoding='utf-8') as f:
                    f.write(bat_content)
                
                self._network_process = subprocess.Popen(['cmd', '/c', 'start', 'cmd', '/k', str(temp_bat)], shell=True)
                
                self.network_disabled = False
                self._log("已执行网络恢复命令")
                self.status_var.set("网络已恢复")
                
        except Exception as e:
            self._log(f"网络操作失败: {str(e)}")
            self.status_var.set("操作失败")
            messagebox.showerror("错误", f"网络操作出错:\n{str(e)}")
    
    def _run_astrum_program(self):
        if not (self.auth.is_admin() or self.auth.has_vip_access()):
            messagebox.showerror("权限不足", "需要至尊版或管理员权限才能访问此功能")
            return
            
        try:
            self._log("正在启动Astrum高级控制程序...")
            self.status_var.set("正在启动高级程序...")
            
            base_path = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path(__file__).parent
            exe_path = base_path / ASTRUM_EXE
            
            if not exe_path.exists():
                raise FileNotFoundError(f"找不到程序文件: {exe_path}")
            
            self._program_process = subprocess.Popen(str(exe_path))
            self._log(f"已启动高级控制程序: {ASTRUM_EXE}")
            self.status_var.set("高级程序运行中")
            
        except Exception as e:
            self._log(f"启动失败: {str(e)}")
            self.status_var.set("启动高级程序失败")
            messagebox.showerror("错误", f"无法启动高级程序:\n{str(e)}")
    
    def _open_key_tools(self):
        if not self.auth.is_admin():
            messagebox.showwarning("权限不足", "需要管理员权限")
            return
        
        self.window.withdraw()
        KeyGenerator(self.window).run()
    
    def _adjust_window_size(self):
        try:
            new_size = simpledialog.askstring(
                "调整窗口大小", 
                "输入新尺寸 (如 1024x768):",
                initialvalue=f"{self.window.winfo_width()}x{self.window.winfo_height()}"
            )
            
            if new_size:
                width, height = map(int, new_size.split('x'))
                if width >= 600 and height >= 400:
                    self.window.geometry(f"{width}x{height}")
                    self._log(f"窗口大小已调整为: {width}x{height}")
                else:
                    messagebox.showwarning("警告", "最小尺寸为600x400")
        except:
            messagebox.showerror("错误", "无效的尺寸格式")
    
    def _toggle_always_on_top(self):
        self.always_on_top = not self.always_on_top
        self.window.attributes('-topmost', self.always_on_top)
        status = "已启用" if self.always_on_top else "已禁用"
        self._log(f"强制置顶 {status}")
        self.status_var.set(f"强制置顶 {status}")
    
    def _apply_font_size(self):
        new_size = self.font_size.get()
        try:
            self.game_text.config(font=("Consolas", new_size))
            self._log(f"手动调整字体大小: {new_size}pt")
        except Exception as e:
            self._log(f"调整字体大小失败: {str(e)}")
    
    def _apply_win_mode(self):
        mode = self.win_mode.get()
        try:
            if mode == "win7":
                self.window.tk.call('tk', 'scaling', 0.95)
                self.style.theme_use('classic')
                style = "Windows 7"
            elif mode == "win10":
                self.window.tk.call('tk', 'scaling', 1.0)
                self.style.theme_use('vista')
                style = "Windows 10"
            else:  # win11
                self.window.tk.call('tk', 'scaling', 1.05)
                self.style.theme_use('winnative')
                style = "Windows 11"
            
            self._log(f"手动调整显示模式: {style}")
        except Exception as e:
            self._log(f"调整显示模式失败: {str(e)}")
    
    def _log(self, message):
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.status_var.set(f"[{timestamp}] {message}")
        self.window.update_idletasks()
        logger.info(message)
    
    def _show_about(self):
        about_msg = f"""极域电子教室控制工具 v{VERSION}

当前用户: {self.auth.get_current_user()}
用户版本: {'管理员' if self.auth.is_admin() else self.auth.get_user_version()}

© 2025 SYSTEM-HTY 版权所有"""
        
        about_dialog = tk.Toplevel(self.window)
        about_dialog.title("关于")
        about_dialog.resizable(False, False)
        
        content_frame = tk.Frame(about_dialog, bg='white', padx=15, pady=15)
        content_frame.pack(fill=tk.BOTH, expand=True)
        
        tk.Label(
            content_frame,
            text=about_msg,
            font=("微软雅黑", 10),
            bg='white',
            justify=tk.LEFT
        ).pack(pady=10)
        
        btn_frame = tk.Frame(content_frame, bg='white')
        btn_frame.pack(pady=10)
        
        ColoredButton(
            btn_frame,
            text="访问B站主页",
            color='#0078d7',
            command=lambda: webbrowser.open(BILIBILI_URL),
            width=15
        ).pack(side=tk.LEFT, padx=10)
        
        ColoredButton(
            btn_frame,
            text="关闭",
            color='#d83b01',
            command=about_dialog.destroy,
            width=15
        ).pack(side=tk.LEFT, padx=10)
    
    def _return_to_main(self):
        if self.return_callback:
            self.window.destroy()
            self.return_callback()
    
    def _on_close(self):
        if messagebox.askokcancel("退出", "确定要退出系统吗？"):
            self.window.destroy()
    
    def run(self):
        self.window.mainloop()

# ===================== 密钥生成器 =====================
class KeyGenerator:
    def __init__(self, parent=None):
        self.parent = parent
        self.window = tk.Toplevel(parent) if parent else tk.Tk()
        self.window.title("密钥生成器")
        self.window.geometry("600x500")
        
        self.keys = []
        self.version = tk.StringVar(value="VIP")
        self.key_count = tk.StringVar(value="10")
        
        self._create_widgets()
    
    def _create_widgets(self):
        main_frame = ttk.Frame(self.window, padding=15)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        ttk.Label(
            main_frame,
            text="极域密钥生成器",
            font=('微软雅黑', 16, 'bold')
        ).pack(pady=10)
        
        control_frame = ttk.LabelFrame(main_frame, text="控制面板", padding=10)
        control_frame.pack(fill=tk.X, pady=(0, 15))
        
        version_frame = ttk.Frame(control_frame)
        version_frame.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(version_frame, text="版本:").pack(side=tk.LEFT)
        versions = [("VIP版 (总和30)", "VIP"), ("PRO版 (总和20)", "PRO"), ("BAS版 (总和10)", "BAS")]
        for text, val in versions:
            ttk.Radiobutton(
                version_frame,
                text=text,
                variable=self.version,
                value=val
            ).pack(side=tk.LEFT, padx=5)
        
        count_frame = ttk.Frame(control_frame)
        count_frame.pack(side=tk.LEFT, padx=20)
        
        ttk.Label(count_frame, text="生成数量:").pack(side=tk.LEFT)
        ttk.Entry(count_frame, textvariable=self.key_count, width=8).pack(side=tk.LEFT)
        ttk.Label(count_frame, text="个").pack(side=tk.LEFT)
        
        btn_frame = ttk.Frame(control_frame)
        btn_frame.pack(side=tk.RIGHT)
        
        ttk.Button(
            btn_frame,
            text="生成密钥",
            command=self.generate_keys,
            width=12
        ).pack(side=tk.LEFT, padx=3)
        
        ttk.Button(
            btn_frame,
            text="复制",
            command=self.copy_keys,
            width=12
        ).pack(side=tk.LEFT, padx=3)
        
        ttk.Button(
            btn_frame,
            text="清空",
            command=self.clear_keys,
            width=12
        ).pack(side=tk.LEFT, padx=3)
        
        ttk.Button(
            btn_frame,
            text="验证",
            command=self.validate_keys,
            width=12
        ).pack(side=tk.LEFT, padx=3)
        
        text_frame = ttk.Frame(main_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)
        
        self.text_area = tk.Text(
            text_frame,
            height=10,
            wrap=tk.WORD,
            font=("Consolas", 11),
            padx=10,
            pady=10
        )
        self.text_area.pack(fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(text_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.text_area.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.text_area.yview)
        
        status_frame = ttk.Frame(main_frame)
        status_frame.pack(fill=tk.X, pady=(10, 0))
        
        self.status = ttk.Label(
            status_frame,
            text="就绪 | 密钥总数: 0",
            relief=tk.SUNKEN,
            font=('微软雅黑', 9),
            width=40
        )
        self.status.pack(side=tk.RIGHT)
    
    def generate_single_key(self, target_sum):
        segments = []
        remaining_sum = target_sum
        
        for _ in range(4):
            segment = []
            segment_sum = 0
            
            if remaining_sum > 0:
                num = random.randint(1, min(9, remaining_sum)) if remaining_sum > 1 else 1
                segment.append(str(num))
                segment_sum += num
                remaining_sum -= num
            
            while len(segment) < 5:
                if remaining_sum > 0 and random.random() < 0.3:
                    num = random.randint(0, min(9, remaining_sum))
                    segment.append(str(num))
                    segment_sum += num
                    remaining_sum -= num
                else:
                    segment.append(random.choice('ABCDEFGHJKLMNPQRSTUVWXYZ'))
            
            random.shuffle(segment)
            segments.append(''.join(segment))
        
        last_segment = []
        
        if remaining_sum > 0:
            num = random.randint(1, min(9, remaining_sum)) if remaining_sum > 1 else 1
            last_segment.append(str(num))
            remaining_sum -= num
        
        while len(last_segment) < 5:
            if remaining_sum > 0 and random.random() < 0.3:
                num = random.randint(0, min(9, remaining_sum))
                last_segment.append(str(num))
                remaining_sum -= num
            else:
                last_segment.append(random.choice('ABCDEFGHJKLMNPQRSTUVWXYZ'))
        
        last_segment.append(self.version.get())
        segments.append(''.join(last_segment))
        
        key = "-".join(segments)
        
        if sum(int(c) for c in key if c.isdigit()) != target_sum:
            return self.generate_single_key(target_sum)
        
        return key
    
    def generate_keys(self):
        try:
            target_count = int(self.key_count.get())
            if target_count <= 0:
                messagebox.showerror("错误", "生成数量必须大于0")
                return
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")
            return
        
        version_map = {"VIP": 30, "PRO": 20, "BAS": 10}
        target_sum = version_map[self.version.get()]
        
        self.keys = []
        self.text_area.delete(1.0, tk.END)
        
        for _ in range(target_count):
            key = self.generate_single_key(target_sum)
            self.keys.append(key)
            self.text_area.insert(tk.END, key + "\n")
        
        self.status.config(text=f"完成! | 共生成 {len(self.keys)} 个密钥")
    
    def validate_keys(self):
        if not self.keys:
            messagebox.showwarning("警告", "没有可验证的密钥")
            return
        
        invalid_keys = []
        version_map = {"VIP": 30, "PRO": 20, "BAS": 10}
        
        for key in self.keys:
            valid, msg = KeyValidator.validate(key)
            if not valid:
                invalid_keys.append(key)
        
        if invalid_keys:
            messagebox.showwarning("验证结果", 
                                f"发现 {len(invalid_keys)} 个无效密钥!\n第一个无效密钥: {invalid_keys[0] if invalid_keys else '无'}")
        else:
            messagebox.showinfo("验证结果", "所有密钥均有效!")
    
    def copy_keys(self):
        if not self.keys:
            messagebox.showwarning("警告", "没有可复制的密钥")
            return
        
        self.window.clipboard_clear()
        self.window.clipboard_append("\n".join(self.keys))
        messagebox.showinfo("成功", f"已复制 {len(self.keys)} 个密钥到剪贴板")
    
    def clear_keys(self):
        if not self.keys or messagebox.askyesno("确认", "确定要清空所有密钥吗?"):
            self.keys = []
            self.text_area.delete(1.0, tk.END)
            self.status.config(text="已清空 | 密钥总数: 0")
    
    def run(self):
        self.window.mainloop()

# ===================== 主菜单 =====================
class MainMenu:
    def __init__(self, auth_system):
        self.auth = auth_system
        self.window = tk.Tk()
        self.window.title(f"主菜单 - 极域控制系统 v{VERSION}")
        self.window.geometry("500x400")
        self.window.minsize(400, 300)
        
        self.style = ttk.Style()
        self.style.theme_use('classic')
        self.window.tk.call('tk', 'scaling', 0.95)
        
        self._create_main_frame()
        self.window.protocol("WM_DELETE_WINDOW", self._on_close)
    
    def _create_main_frame(self):
        main_frame = tk.Frame(self.window, bg='white')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        tk.Label(
            main_frame,
            text="极域控制系统",
            font=("微软雅黑", 16, "bold"),
            bg='white'
        ).pack(pady=20)
        
        user_frame = tk.Frame(main_frame, bg='white')
        user_frame.pack(pady=10)
        
        tk.Label(
            user_frame,
            text=f"用户: {self.auth.get_current_user()}",
            bg='white'
        ).pack(side=tk.LEFT)
        
        version_color = '#0078d7' if self.auth.get_user_version() == 'BAS' else \
                       '#107c10' if self.auth.get_user_version() == 'PRO' else \
                       '#68217a'
        version_text = '(普通版)' if self.auth.get_user_version() == 'BAS' else \
                      '(豪华版)' if self.auth.get_user_version() == 'PRO' else \
                      '(至尊版)'
        
        tk.Label(
            user_frame,
            text=version_text,
            fg='white',
            bg=version_color,
            font=('微软雅黑', 9, 'bold'),
            padx=5
        ).pack(side=tk.LEFT, padx=5)
        
        if self.auth.is_admin():
            tk.Label(
                user_frame,
                text="(管理员)",
                fg='white',
                bg='red',
                font=('微软雅黑', 9,'bold'),
                padx=5
            ).pack(side=tk.LEFT, padx=5)

        btn_frame = tk.Frame(main_frame, bg='white')
        btn_frame.pack(pady=20)

        buttons = [
            ("极域控制工具", self._open_control_tool, '#0078d7'),
            ("密钥工具", self._open_key_tools, '#ff8c00'),
            ("高级控制面板", self._open_admin_panel, '#68217a')
        ]

        for text, command, color in buttons:
            btn = ColoredButton(
                btn_frame,
                text=text,
                color=color,
                command=command,
                width=18
            )
            btn.pack(pady=10)

            if text == "密钥工具" and not self.auth.is_admin():
                btn.config(state=tk.DISABLED, bg='#cccccc')
            elif text == "高级控制面板" and not (self.auth.is_admin() or self.auth.has_vip_access()):
                btn.config(state=tk.DISABLED, bg='#cccccc')

    def _open_control_tool(self):
        self.window.withdraw()
        JiyuControlTool(self.auth, self._return_to_main).run()

    def _open_key_tools(self):
        if not self.auth.is_admin():
            messagebox.showinfo("提示", "请升级至管理员权限后再尝试！")
            return
            
        self.window.withdraw()
        KeyGenerator(self.window).run()

    def _open_admin_panel(self):
        if not (self.auth.is_admin() or self.auth.has_vip_access()):
            messagebox.showerror("权限不足", "需要至尊版或管理员权限才能访问此功能")
            return
        messagebox.showinfo("提示", "高级管理员功能正在开发中")

    def _return_to_main(self):
        self.window.deiconify()

    def _on_close(self):
        if messagebox.askokcancel("退出", "确定要退出系统吗？"):
            self.window.destroy()

    def run(self):
        self.window.mainloop()

# ===================== 登录窗口 =====================
class LoginWindow:
    def __init__(self, auth_system):
        self.auth = auth_system
        self.window = tk.Tk()
        self.window.title(f"极域控制系统 v{VERSION} - 登录")
        self.window.geometry("400x300")
        self.window.resizable(False, False)
        
        self.style = ttk.Style()
        self.style.theme_use('classic')
        self.window.tk.call('tk', 'scaling', 0.95)
        
        self._create_widgets()

    def _create_widgets(self):
        main_frame = tk.Frame(self.window, bg='white')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        tk.Label(
            main_frame,
            text="极域控制系统",
            font=("微软雅黑", 14, "bold"),
            bg='white'
        ).pack(pady=10)
        
        form_frame = tk.Frame(main_frame, bg='white')
        form_frame.pack(pady=20)
        
        tk.Label(
            form_frame,
            text="用户名:",
            bg='white'
        ).grid(row=0, column=0, padx=5, pady=5, sticky="e")
        
        self.username_entry = tk.Entry(
            form_frame,
            width=25,
            font=("微软雅黑", 10)
        )
        self.username_entry.grid(row=0, column=1, padx=5, pady=5)
        
        tk.Label(
            form_frame,
            text="密码:",
            bg='white'
        ).grid(row=1, column=0, padx=5, pady=5, sticky="e")
        
        self.password_entry = tk.Entry(
            form_frame,
            show="*",
            width=25,
            font=("微软雅黑", 10)
        )
        self.password_entry.grid(row=1, column=1, padx=5, pady=5)
        
        self.key_label = tk.Label(form_frame, text="密钥:", bg='white')
        self.key_entry = tk.Entry(form_frame, width=25, font=("微软雅黑", 10))
        
        self.username_entry.bind("<KeyRelease>", self._toggle_key_field)
        
        btn_frame = tk.Frame(main_frame, bg='white')
        btn_frame.pack(pady=20)
        
        ColoredButton(
            btn_frame,
            text="登录",
            color='#0078d7',
            command=self._handle_login,
            width=10
        ).pack(side=tk.LEFT, padx=10)

        ColoredButton(
            btn_frame,
            text="注册",
            color='#107c10',
            command=self._handle_register,
            width=10
        ).pack(side=tk.LEFT, padx=10)

    def _toggle_key_field(self, event):
        username = self.username_entry.get().strip()
        if username == ADMIN_ACCOUNT:
            self.key_label.grid_remove()
            self.key_entry.grid_remove()
        else:
            self.key_label.grid(row=2, column=0, padx=5, pady=5, sticky="e")
            self.key_entry.grid(row=2, column=1, padx=5, pady=5)
    
    def _handle_login(self):
        username = self.username_entry.get().strip()
        password = self.password_entry.get().strip()
        
        if not username or not password:
            messagebox.showerror("错误", "用户名和密码不能为空")
            return
        
        if username == ADMIN_ACCOUNT:
            key = None
        else:
            key = self.key_entry.get().strip()
            if not key:
                messagebox.showerror("错误", "请输入密钥")
                return
        
        success, msg = self.auth.login(username, password, key)
        if success:
            self.window.destroy()
            MainMenu(self.auth).run()
        else:
            messagebox.showerror("错误", msg)
    
    def _handle_register(self):
        username = self.username_entry.get().strip()
        password = self.password_entry.get().strip()
        
        if not username or not password:
            messagebox.showerror("错误", "用户名和密码不能为空")
            return
        
        if len(password) < 6:
            messagebox.showerror("错误", "密码长度至少6位")
            return
        
        success, msg = self.auth.register(username, password)
        if success:
            messagebox.showinfo("成功", msg)
            self.password_entry.delete(0, tk.END)
        else:
            messagebox.showerror("错误", msg)

    def run(self):
        self.window.mainloop()

# ===================== 主程序入口 =====================
if __name__ == "__main__":
    try:
        logger.info("程序启动")
      
        auth_system = AuthSystem()
        LoginWindow(auth_system).run()
    except Exception as e:
        logger.critical(f"程序崩溃: {str(e)}", exc_info=True)
        messagebox.showerror("严重错误", f"程序发生严重错误:\n{str(e)}\n请查看日志文件: {LOG_FILE}")