import tkinter as tk
import os
import subprocess
import sys
import threading
from tkinter import messagebox

from core.constants import THEME_PRESETS, DATA_DIR
from core.storage import save_settings, save_documents, save_todos, save_enterprise, save_action_logs
from core.ui import center_window, create_button, create_card


class SettingsPage:
    def __init__(self, app, parent):
        self.app = app
        self.colors = app.colors
        self.frame = tk.Frame(parent, bg=self.colors["bg"])
        self.quick_vars = {}
        self.holiday_vars = {}
        self.performance_vars = {}
        self.server_vars = {}
        self._build()

    def _build(self):
        self.canvas = tk.Canvas(self.frame, bg=self.colors["bg"], highlightthickness=0)
        self.page_scroll = tk.Scrollbar(self.frame, orient="vertical", command=self.canvas.yview)
        self.scroll_host = tk.Frame(self.canvas, bg=self.colors["bg"])
        self.canvas.configure(yscrollcommand=self.page_scroll.set)
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self._scrollbar_visible = False
        self._scroll_needed = False
        self.canvas_window = self.canvas.create_window((0, 0), window=self.scroll_host, anchor="nw")
        self.scroll_host.bind("<Configure>", self._on_scroll_configure)
        self.canvas.bind("<Configure>", self._on_scroll_configure)

        container = tk.Frame(self.scroll_host, bg=self.colors["bg"])
        container.pack(fill=tk.BOTH, expand=True)

        left = tk.Frame(container, bg=self.colors["bg"])
        left.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        right = tk.Frame(container, bg=self.colors["bg"], width=390)
        right.pack(side=tk.RIGHT, fill=tk.BOTH, padx=(14, 0))
        right.pack_propagate(False)

        self.account_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.mode_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.language_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.font_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.performance_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.theme_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.quick_card = create_card(left, self.colors, fill=tk.X, pady=(0, 14))
        self.holiday_card = create_card(left, self.colors, fill=tk.X)
        self.server_card = create_card(right, self.colors, fill=tk.X, pady=(0, 14))
        self.log_card = create_card(right, self.colors, fill=tk.X, pady=(0, 14))
        self.log_card.configure(height=300)
        self.log_card.pack_propagate(False)
        self.data_card = create_card(right, self.colors, fill=tk.BOTH, expand=True)

        self._build_account()
        # Login/account is handled by the front login screen now, so keep the
        # settings page focused on product preferences and data management.
        self.account_card.pack_forget()
        self._build_mode()
        self._build_language()
        self._build_font()
        self._build_performance()
        self._build_theme()
        self._build_quick()
        self._build_holiday_reminders()
        self._build_server_sync()
        self._build_action_logs()
        self._build_data()

        # Keep Settings simple for normal users. Internal diagnostics, runtime
        # connection panels, and activity logs are still available for testing by
        # setting NEXA_SHOW_INTERNAL_SETTINGS=1 before launching the app.
        if os.environ.get("NEXA_SHOW_INTERNAL_SETTINGS", "0") != "1":
            for card in (self.performance_card, self.server_card, self.log_card):
                try:
                    card.pack_forget()
                except Exception:
                    pass

    def _title(self, parent, title_key, subtitle_key=None):
        box = tk.Frame(parent, bg=self.colors["card"])
        box.pack(fill=tk.X, padx=20, pady=(18, 12))
        title = tk.Label(box, text=self.app.t(title_key), font=("Microsoft YaHei UI", 16, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        title.pack(anchor="w")
        subtitle = None
        if subtitle_key:
            subtitle = tk.Label(box, text=self.app.t(subtitle_key), font=("Microsoft YaHei UI", 9), fg=self.colors["text_secondary"], bg=self.colors["card"], wraplength=650, justify=tk.LEFT)
            subtitle.pack(anchor="w", pady=(4, 0))
        return title, subtitle

    def _inside_scroll_area(self, event):
        try:
            x1, y1 = self.canvas.winfo_rootx(), self.canvas.winfo_rooty()
            x2, y2 = x1 + self.canvas.winfo_width(), y1 + self.canvas.winfo_height()
            return x1 <= event.x_root <= x2 and y1 <= event.y_root <= y2
        except Exception:
            return False

    def _on_scroll_configure(self, event=None):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))
        try:
            self.canvas.itemconfig(self.canvas_window, width=self.canvas.winfo_width())
            needed = self.scroll_host.winfo_reqheight() > self.canvas.winfo_height() + 2
            self._scroll_needed = needed
            if needed and not self._scrollbar_visible:
                self.page_scroll.pack(side=tk.RIGHT, fill=tk.Y)
                self._scrollbar_visible = True
            elif not needed and self._scrollbar_visible:
                self.page_scroll.pack_forget()
                self._scrollbar_visible = False
        except Exception:
            pass

    def _on_mousewheel_linux(self, direction, event):
        active_canvas = getattr(self, "_active_inner_canvas", None)
        if active_canvas is not None:
            try:
                lo, hi = active_canvas.yview()
                if (hi - lo) < 0.999:
                    active_canvas.yview_scroll(direction, "units")
                    return "break"
            except Exception:
                pass
        if self._scroll_needed and self._inside_scroll_area(event):
            self.canvas.yview_scroll(direction, "units")
            return "break"

    def _on_mousewheel(self, event):
        active_canvas = getattr(self, "_active_inner_canvas", None)
        if active_canvas is not None:
            try:
                lo, hi = active_canvas.yview()
                if (hi - lo) < 0.999:
                    active_canvas.yview_scroll(-1 if event.delta > 0 else 1, "units")
                    return "break"
            except Exception:
                pass
        if self._scroll_needed and self._inside_scroll_area(event):
            self.canvas.yview_scroll(-1 if event.delta > 0 else 1, "units")
            return "break"

    def _build_account(self):
        self.account_title, self.account_hint = self._title(self.account_card, "login_title", "login_hint")
        body = tk.Frame(self.account_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))

        self.login_status = tk.Label(body, text="", font=("Microsoft YaHei UI", 11, "bold"), fg=self.colors["primary"], bg=self.colors["primary_light"], padx=12, pady=8)
        self.login_status.pack(anchor="w", fill=tk.X, pady=(0, 14))

        grid = tk.Frame(body, bg=self.colors["card"])
        grid.pack(fill=tk.X)

        self.username_label = tk.Label(grid, text=self.app.t("username_label"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.username_label.grid(row=0, column=0, sticky="w")
        self.username_entry = tk.Entry(grid, font=("Microsoft YaHei UI", 11), relief=tk.FLAT, bd=0, bg=self.colors["bg"], fg=self.colors["text"])
        self.username_entry.grid(row=1, column=0, sticky="ew", ipady=8, pady=(6, 10), padx=(0, 10))

        self.password_label = tk.Label(grid, text=self.app.t("account_password"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.password_label.grid(row=0, column=1, sticky="w")
        self.password_entry = tk.Entry(grid, font=("Microsoft YaHei UI", 11), relief=tk.FLAT, bd=0, bg=self.colors["bg"], fg=self.colors["text"], show="*")
        self.password_entry.grid(row=1, column=1, sticky="ew", ipady=8, pady=(6, 10))

        self.confirm_label = tk.Label(grid, text=self.app.t("account_confirm_password"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.confirm_label.grid(row=2, column=0, sticky="w")
        self.confirm_entry = tk.Entry(grid, font=("Microsoft YaHei UI", 11), relief=tk.FLAT, bd=0, bg=self.colors["bg"], fg=self.colors["text"], show="*")
        self.confirm_entry.grid(row=3, column=0, sticky="ew", ipady=8, pady=(6, 10), padx=(0, 10))

        self.role_label = tk.Label(grid, text=self.app.t("account_role"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.role_label.grid(row=2, column=1, sticky="w")
        self.role_var = tk.StringVar(value="user")
        role_wrap = tk.Frame(grid, bg=self.colors["card"])
        role_wrap.grid(row=3, column=1, sticky="w", pady=(6, 10))
        self.role_user = tk.Radiobutton(role_wrap, text=self.app.t("normal_staff"), variable=self.role_var, value="user", bg=self.colors["card"], activebackground=self.colors["card"], selectcolor=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 9))
        self.role_user.pack(side=tk.LEFT)
        self.role_admin = tk.Radiobutton(role_wrap, text=self.app.t("admin_badge"), variable=self.role_var, value="admin", bg=self.colors["card"], activebackground=self.colors["card"], selectcolor=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 9))
        self.role_admin.pack(side=tk.LEFT, padx=10)

        grid.grid_columnconfigure(0, weight=1)
        grid.grid_columnconfigure(1, weight=1)

        btn_row = tk.Frame(body, bg=self.colors["card"])
        btn_row.pack(fill=tk.X, pady=(4, 0))
        self.login_btn = create_button(btn_row, self.app.t("login_btn"), self.login, self.colors, filled=True)
        self.login_btn.pack(side=tk.LEFT)
        self.create_btn = create_button(btn_row, self.app.t("create_account"), self.create_account, self.colors)
        self.create_btn.pack(side=tk.LEFT, padx=10)
        self.logout_btn = create_button(btn_row, self.app.t("logout_btn"), self.logout, self.colors)
        self.logout_btn.pack(side=tk.LEFT)

    def _build_mode(self):
        self.mode_title, self.mode_hint = self._title(self.mode_card, "mode_section", "mode_hint")
        body = tk.Frame(self.mode_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))
        self.mode_buttons = {}
        mode_items = [("personal", "mode_personal", "mode_personal_desc")]
        if getattr(self.app, "has_enterprise_account", lambda: True)():
            mode_items.append(("enterprise", "mode_enterprise", "mode_enterprise_desc"))
        for mode, label_key, desc_key in mode_items:
            box = tk.Frame(body, bg=self.colors["card_soft"], highlightthickness=1, highlightbackground=self.colors["border"])
            box.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10))
            btn = tk.Button(
                box,
                text=self.app.t(label_key),
                command=lambda m=mode: self.app.set_app_mode(m),
                relief=tk.FLAT,
                bd=0,
                font=("Microsoft YaHei UI", 10, "bold"),
                padx=16,
                pady=10,
                cursor="hand2",
            )
            btn.pack(fill=tk.X, padx=8, pady=(8, 4))
            desc = tk.Label(box, text=self.app.t(desc_key), font=("Microsoft YaHei UI", 9), fg=self.colors["text_secondary"], bg=self.colors["card_soft"], wraplength=280, justify=tk.LEFT)
            desc.pack(fill=tk.X, padx=12, pady=(0, 10))
            self.mode_buttons[mode] = (btn, desc, label_key, desc_key)
        self._update_mode_buttons()

    def _update_mode_buttons(self):
        if not hasattr(self, "mode_buttons"):
            return
        current = self.app.get_app_mode()
        for mode, (btn, desc, label_key, desc_key) in self.mode_buttons.items():
            active = mode == current
            btn.config(
                text=self.app.t(label_key),
                bg=self.colors["primary"] if active else self.colors["card"],
                fg="white" if active else self.colors["text"],
                activebackground=self.colors["primary_dark"] if active else self.colors["primary_light"],
                activeforeground="white" if active else self.colors["primary"],
            )
            desc.config(text=self.app.t(desc_key), bg=self.colors["card_soft"], fg=self.colors["text_secondary"])

    def _build_language(self):
        self.language_title, self.language_hint = self._title(self.language_card, "language_section", "language_hint")
        body = tk.Frame(self.language_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))
        self.lang_buttons = {}
        for code, label in [("zh_CN", "中文"), ("en_US", "English"), ("id_ID", "Indonesia")]:
            btn = tk.Button(body, text=label, command=lambda c=code: self.app.set_language(c), relief=tk.FLAT, bd=0, padx=18, pady=10, cursor="hand2", font=("Microsoft YaHei UI", 10, "bold"))
            btn.pack(side=tk.LEFT, padx=(0, 10))
            self.lang_buttons[code] = btn

    def _build_font(self):
        self.font_title, self.font_hint = self._title(self.font_card, "font_ui_section", "font_ui_hint")
        body = tk.Frame(self.font_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))

        top = tk.Frame(body, bg=self.colors["card"])
        top.pack(fill=tk.X, pady=(0, 10))
        self.font_scale_label = tk.Label(top, text=self.app.t("font_ui_scale_label"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.font_scale_label.pack(side=tk.LEFT)
        self.font_scale_value = tk.Label(top, text="100%", font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["primary"], bg=self.colors["card"])
        self.font_scale_value.pack(side=tk.RIGHT)

        initial_scale = int(round(float(self.app.user_settings.get("font_scale", 1.0)) * 100))
        initial_scale = max(95, min(125, initial_scale))
        # Snap to the nearest preset so the UI is pure-button based.
        self.font_presets = (95, 100, 105, 110, 115, 120, 125)
        initial_scale = min(self.font_presets, key=lambda v: abs(v - initial_scale))
        self.font_scale_var = tk.IntVar(value=initial_scale)

        button_grid = tk.Frame(body, bg=self.colors["card"])
        button_grid.pack(fill=tk.X, pady=(0, 12))
        self.font_preset_buttons = []
        for idx, pct in enumerate(self.font_presets):
            btn = tk.Button(
                button_grid,
                text=f"{pct}%",
                command=lambda v=pct: self._set_font_preset(v),
                relief=tk.FLAT,
                bd=0,
                bg=self.colors["card_soft"],
                fg=self.colors["text_secondary"],
                activebackground=self.colors["primary_light"],
                activeforeground=self.colors["primary"],
                font=("Microsoft YaHei UI", 10, "bold"),
                cursor="hand2",
                padx=12,
                pady=10,
                highlightthickness=1,
                highlightbackground=self.colors["border"],
            )
            btn.grid(row=0, column=idx, sticky="ew", padx=(0 if idx == 0 else 5, 0 if idx == len(self.font_presets) - 1 else 5))
            button_grid.grid_columnconfigure(idx, weight=1, uniform="font_scale_buttons")
            self.font_preset_buttons.append(btn)

        self.font_preview = tk.Label(body, text=self.app.t("font_ui_preview_text"), font=("Microsoft YaHei UI", 11), fg=self.colors["text_secondary"], bg=self.colors["card_soft"], anchor="w", justify=tk.LEFT, padx=12, pady=10)
        self.font_preview.pack(fill=tk.X)
        self.font_apply_btn = create_button(body, self.app.t("font_apply_btn"), self.apply_font_scale, self.colors, filled=True)
        self.font_apply_btn.pack(anchor="w", pady=(12, 0))
        self._update_font_preview()

    def _set_font_preset(self, value):
        self.font_scale_var.set(int(value))
        self._update_font_preview()

    def _update_font_preview(self):
        if not hasattr(self, "font_scale_var"):
            return
        pct = int(self.font_scale_var.get())
        if hasattr(self, "font_scale_value"):
            self.font_scale_value.config(text=f"{pct}%")
        preview_size = max(10, min(18, int(round(11 * pct / 100))))
        if hasattr(self, "font_preview"):
            self.font_preview.config(font=("Microsoft YaHei UI", preview_size), text=self.app.t("font_ui_preview_text"))
        if hasattr(self, "font_preset_buttons"):
            for btn in self.font_preset_buttons:
                active = btn.cget("text") == f"{pct}%"
                btn.config(
                    bg=self.colors["primary"] if active else self.colors["card_soft"],
                    fg="white" if active else self.colors["text_secondary"],
                    activebackground=self.colors["primary_dark"] if active else self.colors["primary_light"],
                    activeforeground="white" if active else self.colors["primary"],
                    highlightbackground=self.colors["primary"] if active else self.colors["border"],
                )

    def _performance_profile_text(self):
        profile = getattr(self.app, "device_profile", {}) or {}
        tier = getattr(self.app, "_effective_performance_tier", lambda: self.app.user_settings.get("performance_tier", "auto"))()
        tier_label = self._performance_tier_label(tier) if hasattr(self, "_performance_tier_label") else str(tier)
        summary = getattr(self.app, "performance_summary", lambda: {"avg_ms": 0, "max_ms": 0, "slow_count": 0})()
        return self.app.t("performance_device_profile").format(
            tier=tier_label,
            cpu=profile.get("cpu_count", "-"),
            screen=f"{profile.get('screen_width', '-') }×{profile.get('screen_height', '-')}",
            dpi=profile.get("dpi_scaling", "-"),
            avg=summary.get("avg_ms", 0),
            max=summary.get("max_ms", 0),
            slow=summary.get("slow_count", 0),
        )

    def apply_font_scale(self):
        pct = int(self.font_scale_var.get())
        self.app.set_font_scale(pct / 100.0)

    def _performance_tier_label(self, value):
        key = str(value or "auto")
        mapping = {
            "auto": "performance_tier_auto",
            "balanced": "performance_tier_balanced",
            "low_power": "performance_tier_low_power",
        }
        return self.app.t(mapping.get(key, "performance_tier_auto"))

    def _performance_tier_value(self, label):
        label = str(label or "")
        for key in ("auto", "balanced", "low_power"):
            if label == self._performance_tier_label(key):
                return key
        return "auto"

    def _build_performance(self):
        self.performance_title, self.performance_hint = self._title(self.performance_card, "performance_section", "performance_hint")
        body = tk.Frame(self.performance_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))

        self.performance_tier_var = tk.StringVar(value=self._performance_tier_label(self.app.user_settings.get("performance_tier", "auto") or "auto"))
        tier_row = tk.Frame(body, bg=self.colors["card"])
        tier_row.pack(fill=tk.X, pady=(0, 12))
        tk.Label(tier_row, text=self.app.t("performance_tier_label"), bg=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 10, "bold")).pack(side=tk.LEFT)
        self.performance_tier_menu = tk.OptionMenu(
            tier_row,
            self.performance_tier_var,
            self._performance_tier_label("auto"),
            self._performance_tier_label("balanced"),
            self._performance_tier_label("low_power"),
            command=lambda value: self.app.set_performance_tier(self._performance_tier_value(value)),
        )
        self.performance_tier_menu.configure(
            bg=self.colors["card_soft"],
            fg=self.colors["text"],
            activebackground=self.colors["primary_light"],
            activeforeground=self.colors["primary"],
            relief=tk.FLAT,
            bd=0,
            font=("Microsoft YaHei UI", 9, "bold"),
            width=16,
            cursor="hand2",
        )
        self.performance_tier_menu.pack(side=tk.LEFT, padx=(10, 0))
        self.performance_tier_desc = tk.Label(body, text=self.app.t("performance_tier_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
        self.performance_tier_desc.pack(anchor="w", pady=(0, 12))
        self.show_internal_runtime_tools = os.environ.get("NEXA_SHOW_INTERNAL_SETTINGS", "0") == "1"
        self.performance_profile_label = None
        if self.show_internal_runtime_tools:
            self.performance_profile_label = tk.Label(
                body,
                text=self._performance_profile_text(),
                bg=self.colors["card_soft"],
                fg=self.colors["text_secondary"],
                font=("Microsoft YaHei UI", 9, "bold"),
                wraplength=650,
                justify=tk.LEFT,
                padx=12,
                pady=8,
            )
            self.performance_profile_label.pack(fill=tk.X, anchor="w", pady=(0, 12))
        preset_row = tk.Frame(body, bg=self.colors["card"])
        preset_row.pack(fill=tk.X, pady=(0, 12))
        self.performance_auto_btn = create_button(preset_row, self.app.t("performance_preset_auto"), lambda: self.app.apply_performance_preset("auto"), self.colors)
        self.performance_auto_btn.pack(side=tk.LEFT, padx=(0, 8))
        self.performance_balanced_btn = create_button(preset_row, self.app.t("performance_preset_balanced"), lambda: self.app.apply_performance_preset("balanced"), self.colors)
        self.performance_balanced_btn.pack(side=tk.LEFT, padx=(0, 8))
        self.performance_low_btn = create_button(preset_row, self.app.t("performance_preset_low_power"), lambda: self.app.apply_performance_preset("low_power"), self.colors, filled=True)
        self.performance_low_btn.pack(side=tk.LEFT)

        self.smooth_restore_var = tk.BooleanVar(value=bool(self.app.user_settings.get("smooth_restore", True)))
        self.restore_full_cover_var = tk.BooleanVar(value=bool(self.app.user_settings.get("restore_full_window_cover", True)))
        self.light_switch_var = tk.BooleanVar(value=bool(self.app.user_settings.get("lightweight_page_switch", True)))
        self.close_to_tray_var = tk.BooleanVar(value=bool(self.app.user_settings.get("close_to_tray", True)))
        # These two source-mode variables were previously referenced before creation.
        # In a packaged EXE the Tk callback error is not visible, so it looked like
        # the whole Settings page was frozen. Keep them initialized before any
        # Checkbutton uses them.
        self.source_mode_close_direct_var = tk.BooleanVar(value=bool(self.app.user_settings.get("source_mode_close_direct", True)))
        self.source_mode_force_os_exit_var = tk.BooleanVar(value=bool(self.app.user_settings.get("source_mode_force_os_exit", True)))

        self.smooth_restore_check = tk.Checkbutton(
            body,
            text=self.app.t("performance_smooth_restore"),
            variable=self.smooth_restore_var,
            command=lambda: self.app.set_smooth_restore(self.smooth_restore_var.get()),
            bg=self.colors["card"],
            activebackground=self.colors["card"],
            selectcolor=self.colors["card"],
            fg=self.colors["text"],
            font=("Microsoft YaHei UI", 10, "bold"),
        )
        self.smooth_restore_check.pack(anchor="w", pady=(0, 6))
        self.smooth_restore_desc = tk.Label(body, text=self.app.t("performance_smooth_restore_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
        self.smooth_restore_desc.pack(anchor="w", pady=(0, 12))

        self.restore_full_cover_check = tk.Checkbutton(
            body,
            text=self.app.t("performance_restore_full_cover"),
            variable=self.restore_full_cover_var,
            command=lambda: self.app.set_restore_full_window_cover(self.restore_full_cover_var.get()),
            bg=self.colors["card"],
            activebackground=self.colors["card"],
            selectcolor=self.colors["card"],
            fg=self.colors["text"],
            font=("Microsoft YaHei UI", 10, "bold"),
        )
        self.restore_full_cover_check.pack(anchor="w", pady=(0, 6))
        self.restore_full_cover_desc = tk.Label(body, text=self.app.t("performance_restore_full_cover_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
        self.restore_full_cover_desc.pack(anchor="w", pady=(0, 12))

        self.light_switch_check = tk.Checkbutton(
            body,
            text=self.app.t("performance_light_switch"),
            variable=self.light_switch_var,
            command=lambda: self.app.set_lightweight_page_switch(self.light_switch_var.get()),
            bg=self.colors["card"],
            activebackground=self.colors["card"],
            selectcolor=self.colors["card"],
            fg=self.colors["text"],
            font=("Microsoft YaHei UI", 10, "bold"),
        )
        self.light_switch_check.pack(anchor="w", pady=(0, 6))
        self.light_switch_desc = tk.Label(body, text=self.app.t("performance_light_switch_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
        self.light_switch_desc.pack(anchor="w")
        self.close_to_tray_check = tk.Checkbutton(
            body,
            text=self.app.t("performance_close_to_tray"),
            variable=self.close_to_tray_var,
            command=lambda: self.app.set_close_to_tray(self.close_to_tray_var.get()),
            bg=self.colors["card"],
            activebackground=self.colors["card"],
            selectcolor=self.colors["card"],
            fg=self.colors["text"],
            font=("Microsoft YaHei UI", 10, "bold"),
        )
        self.close_to_tray_check.pack(anchor="w", pady=(12, 6))
        self.close_to_tray_desc = tk.Label(body, text=self.app.t("performance_close_to_tray_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
        self.close_to_tray_desc.pack(anchor="w")

        if self.show_internal_runtime_tools:
            self.source_mode_close_direct_check = tk.Checkbutton(
                body,
                text=self.app.t("performance_source_close_direct"),
                variable=self.source_mode_close_direct_var,
                command=lambda: self.app.set_source_mode_close_direct(self.source_mode_close_direct_var.get()),
                bg=self.colors["card"],
                fg=self.colors["text"],
                activebackground=self.colors["card"],
                selectcolor=self.colors["card"],
                font=("Microsoft YaHei UI", 10),
            )
            self.source_mode_close_direct_check.pack(anchor="w", pady=(12, 6))
            self.source_mode_close_direct_desc = tk.Label(body, text=self.app.t("performance_source_close_direct_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
            self.source_mode_close_direct_desc.pack(anchor="w")

            self.source_mode_force_os_exit_check = tk.Checkbutton(
                body,
                text=self.app.t("performance_source_force_exit"),
                variable=self.source_mode_force_os_exit_var,
                command=lambda: self.app.set_source_mode_force_os_exit(self.source_mode_force_os_exit_var.get()),
                bg=self.colors["card"],
                fg=self.colors["text"],
                activebackground=self.colors["card"],
                selectcolor=self.colors["card"],
                font=("Microsoft YaHei UI", 10),
            )
            self.source_mode_force_os_exit_check.pack(anchor="w", pady=(12, 6))
            self.source_mode_force_os_exit_desc = tk.Label(body, text=self.app.t("performance_source_force_exit_desc"), bg=self.colors["card"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=650, justify=tk.LEFT)
            self.source_mode_force_os_exit_desc.pack(anchor="w")
        else:
            self.source_mode_close_direct_check = None
            self.source_mode_close_direct_desc = None
            self.source_mode_force_os_exit_check = None
            self.source_mode_force_os_exit_desc = None

    def _build_theme(self):
        self.theme_title, self.theme_hint = self._title(self.theme_card, "theme_title", "theme_hint")
        body = tk.Frame(self.theme_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 18))
        self.theme_buttons = {}
        current = self.app.user_settings.get("theme", "blue")
        for idx, (theme_id, info) in enumerate(THEME_PRESETS.items()):
            preview = tk.Frame(body, bg=self.colors["card"], highlightthickness=1, highlightbackground=self.colors["border"])
            preview.grid(row=idx // 3, column=idx % 3, sticky="ew", padx=(0, 10), pady=6)
            body.grid_columnconfigure(idx % 3, weight=1)
            swatches = tk.Frame(preview, bg=self.colors["card"])
            swatches.pack(fill=tk.X, padx=10, pady=(9, 4))
            for color_key in ("primary", "primary_light", "bg"):
                tk.Label(swatches, text="", bg=info.get(color_key, "#FFFFFF"), width=4, height=1).pack(side=tk.LEFT, padx=(0, 4))
            btn = tk.Button(
                preview,
                text=self.app.t(info.get("name_key", theme_id)),
                command=lambda tid=theme_id: self.select_theme(tid),
                bg=self.colors["primary"] if theme_id == current else self.colors["card_soft"],
                fg="white" if theme_id == current else self.colors["text"],
                activebackground=self.colors["primary_light"],
                activeforeground=self.colors["primary"],
                relief=tk.FLAT,
                bd=0,
                font=("Microsoft YaHei UI", 9, "bold"),
                padx=8,
                pady=8,
                cursor="hand2",
            )
            btn.pack(fill=tk.X, padx=10, pady=(0, 10))
            self.theme_buttons[theme_id] = btn

    def select_theme(self, theme_id):
        # Theme is applied live by rebuilding the shell, so this page will be recreated.
        self.app.set_theme(theme_id)

    def _build_quick(self):
        self.quick_title, self.quick_hint = self._title(self.quick_card, "quick_settings_title", "quick_modules_hint")
        body = tk.Frame(self.quick_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))
        items = [
            ("focus", "quick_show_focus"),
            ("calendar", "quick_show_calendar"),
            ("task", "quick_show_task"),
            ("note", "quick_show_note"),
            ("chat", "quick_show_chat"),
            ("cloud", "quick_show_cloud"),
            ("enterprise", "quick_show_enterprise"),
            ("ai", "quick_show_ai"),
        ]
        self.quick_checks = {}
        for i, (key, text_key) in enumerate(items):
            var = tk.BooleanVar(value=self.app.get_quick_actions().get(key, True))
            self.quick_vars[key] = var
            cb = tk.Checkbutton(
                body, text=self.app.t(text_key), variable=var,
                command=lambda k=key, v=var: self.app.set_quick_action(k, v.get()),
                bg=self.colors["card"], activebackground=self.colors["card"], selectcolor=self.colors["card"],
                fg=self.colors["text"], font=("Microsoft YaHei UI", 10), anchor="w"
            )
            cb.grid(row=i // 3, column=i % 3, sticky="w", pady=6, padx=(0, 24))
            self.quick_checks[key] = (cb, text_key)

    def _build_holiday_reminders(self):
        self.holiday_title, self.holiday_hint = self._title(self.holiday_card, "holiday_reminder_section", "holiday_reminder_hint")
        body = tk.Frame(self.holiday_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 20))
        self.holiday_vars["china"] = tk.BooleanVar(value=self.app.get_holiday_reminders().get("china", True))
        self.holiday_vars["indonesia"] = tk.BooleanVar(value=self.app.get_holiday_reminders().get("indonesia", True))
        self.china_holiday_cb = tk.Checkbutton(body, text=self.app.t("holiday_remind_china"), variable=self.holiday_vars["china"], command=lambda: self.app.set_holiday_reminder("china", self.holiday_vars["china"].get()), bg=self.colors["card"], activebackground=self.colors["card"], selectcolor=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 10))
        self.china_holiday_cb.pack(anchor="w", pady=4)
        self.indonesia_holiday_cb = tk.Checkbutton(body, text=self.app.t("holiday_remind_indonesia"), variable=self.holiday_vars["indonesia"], command=lambda: self.app.set_holiday_reminder("indonesia", self.holiday_vars["indonesia"].get()), bg=self.colors["card"], activebackground=self.colors["card"], selectcolor=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 10))
        self.indonesia_holiday_cb.pack(anchor="w", pady=4)
        days_row = tk.Frame(body, bg=self.colors["card"])
        days_row.pack(anchor="w", pady=(8, 0))
        self.days_label = tk.Label(days_row, text=self.app.t("holiday_remind_days"), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"])
        self.days_label.pack(side=tk.LEFT, padx=(0, 10))
        self.days_var = tk.IntVar(value=int(self.app.get_holiday_reminders().get("days_before", 1)))
        self.days_spin = tk.Spinbox(days_row, from_=0, to=14, width=5, textvariable=self.days_var, command=lambda: self.app.set_holiday_reminder("days_before", self.days_var.get()), font=("Microsoft YaHei UI", 10), relief=tk.FLAT, bg=self.colors["bg"])
        self.days_spin.pack(side=tk.LEFT)


    def _build_action_logs(self):
        self.log_title, self.log_hint = self._title(self.log_card, "action_log_title", "action_log_hint")

        body = tk.Frame(self.log_card, bg=self.colors["card"])
        body.pack(fill=tk.BOTH, expand=True, padx=16, pady=(0, 12))

        top = tk.Frame(body, bg=self.colors["card"])
        top.pack(fill=tk.X, pady=(0, 8))
        self.log_clear_btn = create_button(top, self.app.t("action_log_clear"), self.app.clear_action_logs, self.colors)
        self.log_clear_btn.pack(side=tk.RIGHT)
        self.log_open_all_btn = create_button(top, self.app.t("action_log_open_all"), self.open_all_action_logs, self.colors)
        self.log_open_all_btn.pack(side=tk.RIGHT, padx=(0, 8))

        self.log_canvas = tk.Canvas(body, bg=self.colors["card"], highlightthickness=0)
        self.log_scrollbar = tk.Scrollbar(body, orient="vertical", command=self.log_canvas.yview)
        self.log_inner = tk.Frame(self.log_canvas, bg=self.colors["card"])
        self.log_canvas.configure(yscrollcommand=self.log_scrollbar.set)
        self.log_window = self.log_canvas.create_window((0, 0), window=self.log_inner, anchor="nw")
        self.log_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.log_scrollbar_visible = False

        self.log_inner.bind("<Configure>", self._update_log_scrollbar)
        self.log_canvas.bind("<Configure>", self._update_log_scrollbar)
        self.log_canvas.bind("<Enter>", lambda e: setattr(self, "_active_inner_canvas", self.log_canvas))
        self.log_inner.bind("<Enter>", lambda e: setattr(self, "_active_inner_canvas", self.log_canvas))

        self._render_action_logs()


    def open_all_action_logs(self):
        logs = self.app.action_logs.get("items", []) if isinstance(getattr(self.app, "action_logs", {}), dict) else []
        logs = list(reversed(logs))
        dlg = tk.Toplevel(self.app.root)
        dlg.title(self.app.t("action_log_all_title"))
        dlg.configure(bg=self.colors["bg"])
        dlg.transient(self.app.root)
        center_window(dlg, self.app.root, 860, 620, min_width=720, min_height=480)

        header = tk.Frame(dlg, bg=self.colors["card"], highlightthickness=1, highlightbackground=self.colors["border"])
        header.pack(fill=tk.X, padx=16, pady=(16, 10))
        tk.Label(header, text=self.app.t("action_log_all_title"), bg=self.colors["card"], fg=self.colors["text"], font=("Microsoft YaHei UI", 17, "bold")).pack(side=tk.LEFT, padx=16, pady=14)
        tk.Label(header, text=self.app.t("action_log_count").format(count=len(logs)), bg=self.colors["primary_light"], fg=self.colors["primary"], font=("Microsoft YaHei UI", 10, "bold"), padx=12, pady=6).pack(side=tk.RIGHT, padx=16)

        body = tk.Frame(dlg, bg=self.colors["bg"])
        body.pack(fill=tk.BOTH, expand=True, padx=16, pady=(0, 16))
        canvas = tk.Canvas(body, bg=self.colors["bg"], highlightthickness=0)
        scrollbar = tk.Scrollbar(body, orient="vertical", command=canvas.yview)
        inner = tk.Frame(canvas, bg=self.colors["bg"])
        canvas.configure(yscrollcommand=scrollbar.set)
        win = canvas.create_window((0, 0), window=inner, anchor="nw")
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        def sync(_=None):
            canvas.configure(scrollregion=canvas.bbox("all"))
            canvas.itemconfig(win, width=max(canvas.winfo_width() - 4, 300))
        inner.bind("<Configure>", sync)
        canvas.bind("<Configure>", sync)

        if not logs:
            tk.Label(inner, text=self.app.t("action_log_empty"), bg=self.colors["bg"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 11), pady=24).pack(fill=tk.X)
        for item in logs:
            card = tk.Frame(inner, bg=self.colors["card"], highlightthickness=1, highlightbackground=self.colors["border"])
            card.pack(fill=tk.X, pady=5)
            title = item.get("action", "")
            module = item.get("module", "")
            detail = item.get("detail", "")
            time_text = item.get("time", "")
            user = item.get("user", "")
            tk.Label(card, text=f"{title}  {module}".strip(), font=("Microsoft YaHei UI", 10, "bold"), fg=self.colors["text"], bg=self.colors["card"], anchor="w").pack(fill=tk.X, padx=12, pady=(10, 3))
            sub = f"{time_text}"
            if user:
                sub += f" · {user}"
            if detail:
                sub += f" · {detail}"
            tk.Label(card, text=sub, font=("Microsoft YaHei UI", 9), fg=self.colors["text_secondary"], bg=self.colors["card"], wraplength=760, justify=tk.LEFT, anchor="w").pack(fill=tk.X, padx=12, pady=(0, 10))

        footer = tk.Frame(dlg, bg=self.colors["bg"])
        footer.pack(fill=tk.X, padx=16, pady=(0, 16))
        create_button(footer, self.app.t("schedule_cancel"), dlg.destroy, self.colors).pack(side=tk.RIGHT)

    def _update_log_scrollbar(self, event=None):
        if not hasattr(self, "log_canvas"):
            return
        self.log_canvas.configure(scrollregion=self.log_canvas.bbox("all"))
        try:
            self.log_canvas.itemconfig(self.log_window, width=max(self.log_canvas.winfo_width() - 4, 250))
            needed = self.log_inner.winfo_reqheight() > self.log_canvas.winfo_height() + 2
            if needed and not getattr(self, "log_scrollbar_visible", False):
                self.log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
                self.log_scrollbar_visible = True
            elif not needed and getattr(self, "log_scrollbar_visible", False):
                self.log_scrollbar.pack_forget()
                self.log_scrollbar_visible = False
        except Exception:
            pass

    def _render_action_logs(self):
        if not hasattr(self, "log_inner"):
            return
        for child in self.log_inner.winfo_children():
            child.destroy()

        logs = self.app.action_logs.get("items", []) if isinstance(getattr(self.app, "action_logs", {}), dict) else []
        logs = list(reversed(logs[-50:]))
        if not logs:
            tk.Label(
                self.log_inner,
                text=self.app.t("action_log_empty"),
                font=("Microsoft YaHei UI", 10),
                fg=self.colors["text_secondary"],
                bg=self.colors["card"],
                pady=16,
            ).pack(fill=tk.X)
            self._update_log_scrollbar()
            return

        for item in logs:
            card = tk.Frame(self.log_inner, bg=self.colors["card_soft"], highlightthickness=1, highlightbackground=self.colors["border"])
            card.pack(fill=tk.X, pady=4)
            title = item.get("action", "")
            module = item.get("module", "")
            detail = item.get("detail", "")
            time_text = item.get("time", "")
            user = item.get("user", "")

            tk.Label(
                card,
                text=f"{title}  {module}".strip(),
                font=("Microsoft YaHei UI", 9, "bold"),
                fg=self.colors["text"],
                bg=self.colors["card_soft"],
                anchor="w",
            ).pack(fill=tk.X, padx=10, pady=(8, 2))

            sub = f"{time_text}"
            if user:
                sub += f" · {user}"
            if detail:
                sub += f" · {detail}"
            tk.Label(
                card,
                text=sub,
                font=("Microsoft YaHei UI", 8),
                fg=self.colors["text_secondary"],
                bg=self.colors["card_soft"],
                wraplength=300,
                justify=tk.LEFT,
                anchor="w",
            ).pack(fill=tk.X, padx=10, pady=(0, 8))
        self._update_log_scrollbar()


    def _build_server_sync(self):
        self.server_title, self.server_hint = self._title(self.server_card, "server_sync_section", "server_sync_hint")
        body = tk.Frame(self.server_card, bg=self.colors["card"])
        body.pack(fill=tk.X, padx=20, pady=(0, 18))
        cfg = self.app.get_server_sync_config()
        self.server_user_configurable = bool(cfg.get("user_configurable", False))
        self.server_managed_by_system = bool(cfg.get("managed_by_system", True))

        self.server_managed_label = tk.Label(
            body,
            text=self.app.t("server_sync_system_managed"),
            bg=self.colors["primary_light"],
            fg=self.colors["primary"],
            font=("Microsoft YaHei UI", 9, "bold"),
            anchor="w",
            padx=10,
            pady=7,
        )
        self.server_managed_label.pack(fill=tk.X, pady=(0, 8))
        self.server_managed_hint = tk.Label(
            body,
            text=self.app.t("server_sync_user_locked"),
            bg=self.colors["card"],
            fg=self.colors["text_secondary"],
            font=("Microsoft YaHei UI", 8),
            wraplength=315,
            justify=tk.LEFT,
            anchor="w",
        )
        self.server_managed_hint.pack(fill=tk.X, pady=(0, 10))

        # v2026.06.20.14: networking is a system deployment feature, not a
        # normal-user settings form.  Show read-only status only, so users do not
        # need to understand server URLs/tokens and cannot accidentally break sync.
        self.server_summary = tk.Frame(body, bg=self.colors["card_soft"], highlightthickness=1, highlightbackground=self.colors["border"])
        self.server_summary.pack(fill=tk.X, pady=(0, 10))
        rows = [
            ("server_sync_deployment_mode", self._deployment_mode_text(cfg)),
            ("server_sync_base_url", self._masked_origin(cfg.get("base_url", ""))),
            ("server_sync_workspace_id", str(cfg.get("workspace_id") or self.app.t("server_sync_not_configured"))),
            ("server_sync_config_source", self._server_source_text(compact=True)),
        ]
        self.server_summary_labels = []
        for idx, (label_key, value) in enumerate(rows):
            row = tk.Frame(self.server_summary, bg=self.colors["card_soft"])
            row.pack(fill=tk.X, padx=10, pady=(8 if idx == 0 else 2, 8 if idx == len(rows) - 1 else 2))
            label = tk.Label(row, text=self.app.t(label_key), bg=self.colors["card_soft"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 8, "bold"), width=16, anchor="w")
            label.pack(side=tk.LEFT)
            value_label = tk.Label(row, text=value, bg=self.colors["card_soft"], fg=self.colors["text"], font=("Microsoft YaHei UI", 8), anchor="w", justify=tk.LEFT, wraplength=185)
            value_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
            self.server_summary_labels.append((label, value_label, label_key))

        self.server_status = tk.Label(body, text="", bg=self.colors["card_soft"], fg=self.colors["text_secondary"], font=("Microsoft YaHei UI", 9), wraplength=315, justify=tk.LEFT, anchor="w", padx=10, pady=8)
        self.server_status.pack(fill=tk.X, pady=(0, 8))
        self.server_audit_hint = tk.Label(
            body,
            text=self.app.t("server_sync_network_audit_hint"),
            bg=self.colors["card"],
            fg=self.colors.get("text_muted", self.colors.get("text_light", self.colors["text_secondary"])),
            font=("Microsoft YaHei UI", 8),
            wraplength=315,
            justify=tk.LEFT,
            anchor="w",
        )
        self.server_audit_hint.pack(fill=tk.X, pady=(0, 8))

        self.server_readiness = tk.Label(
            body,
            text="",
            bg=self.colors["card_soft"],
            fg=self.colors["text_secondary"],
            font=("Microsoft YaHei UI", 8),
            wraplength=315,
            justify=tk.LEFT,
            anchor="w",
            padx=10,
            pady=8,
        )
        self.server_readiness.pack(fill=tk.X, pady=(0, 8))

        btn_col = tk.Frame(body, bg=self.colors["card"])
        btn_col.pack(fill=tk.X)
        self.server_test_btn = create_button(btn_col, self.app.t("server_sync_test"), self.test_server_sync, self.colors)
        self.server_test_btn.pack(anchor="w", pady=(0, 8))
        self.server_snapshot_btn = create_button(btn_col, self.app.t("server_sync_prepare_snapshot"), self.prepare_sync_snapshot, self.colors)
        self.server_snapshot_btn.pack(anchor="w", pady=(0, 8))
        self.server_repair_queue_btn = create_button(btn_col, self.app.t("server_sync_repair_queue"), self.repair_sync_queue, self.colors)
        self.server_repair_queue_btn.pack(anchor="w", pady=(0, 8))
        self.server_checkpoints_btn = create_button(btn_col, self.app.t("server_sync_open_checkpoints"), self.open_preflight_checkpoints, self.colors)
        self.server_checkpoints_btn.pack(anchor="w", pady=(0, 8))
        self.server_maintenance_btn = create_button(btn_col, self.app.t("server_sync_open_maintenance"), self.open_offline_maintenance_report, self.colors)
        self.server_maintenance_btn.pack(anchor="w", pady=(0, 8))
        self.server_template_btn = create_button(btn_col, self.app.t("server_sync_open_template"), self.open_server_template, self.colors)
        self.server_template_btn.pack(anchor="w", pady=(0, 8))
        self.server_guide_btn = create_button(btn_col, self.app.t("server_sync_open_guide"), self.open_server_deployment_guide, self.colors)
        self.server_guide_btn.pack(anchor="w")
        self._refresh_server_status()

    def _masked_origin(self, url):
        text = str(url or "").strip()
        if not text:
            return self.app.t("server_sync_not_configured")
        try:
            from urllib.parse import urlparse
            if not text.startswith(("http://", "https://")):
                text = "https://" + text
            parsed = urlparse(text)
            host = parsed.netloc or parsed.path
            scheme = parsed.scheme or "https"
            return f"{scheme}://{host}"
        except Exception:
            return self.app.t("server_sync_configured_hidden")

    def _deployment_mode_text(self, cfg):
        if not cfg.get("enabled"):
            return self.app.t("server_sync_runtime_local")
        if cfg.get("offline_mode"):
            return self.app.t("server_sync_runtime_local")
        mode = str(cfg.get("deployment_mode") or "server").lower()
        if mode == "hybrid":
            return self.app.t("server_sync_runtime_hybrid")
        return self.app.t("server_sync_runtime_online")

    def _server_source_text(self, compact=False):
        cfg = self.app.get_server_sync_config()
        source = str(cfg.get("config_source") or "not_configured")
        if source == "not_configured":
            source_text = self.app.t("server_sync_source_none")
        elif source == "environment":
            source_text = self.app.t("server_sync_source_environment")
        elif source.startswith("invalid:"):
            source_text = self.app.t("server_sync_source_invalid")
        else:
            source_text = self.app.t("server_sync_source_file")
        mode_key = "server_sync_runtime_online" if cfg.get("enabled") and not cfg.get("offline_mode") else "server_sync_runtime_local"
        auto_key = "server_sync_auto_connect_on" if cfg.get("auto_connect") else "server_sync_auto_connect_off"
        if compact:
            return source_text
        return f"{self.app.t('server_sync_config_source')}: {source_text} · {self.app.t(mode_key)} · {self.app.t(auto_key)}"

    def _server_form_values(self):
        return {}

    def save_server_sync(self):
        self.app.save_server_sync_config()
        self._refresh_server_status(self.app.t("server_sync_system_managed"))

    def test_server_sync(self):
        self.app.save_server_sync_config()
        self.server_test_btn.config(state=tk.DISABLED)
        self._refresh_server_status(self.app.t("server_sync_testing"))
        def done(ok, status_key, detail):
            try:
                text = self.app.t(status_key)
                if detail:
                    text = f"{text} · {detail}"
                self._refresh_server_status(text, ok=ok)
                self.server_test_btn.config(state=tk.NORMAL)
            except Exception:
                pass
        self.app.test_server_connection_async(done)

    def _open_path(self, path):
        try:
            path = os.fspath(path)
            if sys.platform.startswith("win"):
                os.startfile(path)
            elif sys.platform == "darwin":
                subprocess.Popen(["open", path])
            else:
                subprocess.Popen(["xdg-open", path])
        except Exception as exc:
            messagebox.showerror(self.app.t("error_title"), str(exc))

    def open_server_template(self):
        self._open_path(self.app.base_dir / "server_config.template.json")

    def open_preflight_checkpoints(self):
        try:
            self.app.create_network_preflight_checkpoint("manual_settings_open", force=True)
            self.app.get_checkpoint_restore_dry_run(write_report=True)
            self.app.get_offline_maintenance_report(write_report=True)
        except Exception:
            pass
        self._open_path(DATA_DIR / "preflight_checkpoints")

    def open_offline_maintenance_report(self):
        try:
            self.app.get_offline_maintenance_report(write_report=True)
        except Exception:
            pass
        self._open_path(DATA_DIR / "offline_maintenance_latest.json")

    def open_server_deployment_guide(self):
        self._open_path(self.app.base_dir / "docs" / "SERVER_DEPLOYMENT_READY_20260620_14_CN.md")

    def prepare_sync_snapshot(self):
        item = self.app.prepare_sync_snapshot()
        self._refresh_server_status(self.app.t("server_sync_snapshot_prepared"))
        messagebox.showinfo(self.app.t("success_title"), self.app.t("server_sync_snapshot_prepared"))

    def repair_sync_queue(self):
        ok = self.app.repair_sync_queue_local()
        self._refresh_server_status(self.app.t("server_sync_queue_repaired") if ok else None, ok=ok)
        if ok:
            messagebox.showinfo(self.app.t("success_title"), self.app.t("server_sync_queue_repaired"))

    def _refresh_server_status(self, message=None, ok=None):
        if not hasattr(self, "server_status"):
            return
        summary = self.app.get_sync_queue_summary()
        queue_text = self.app.t("server_sync_queue_status").format(
            total=summary.get("total", 0),
            pending=summary.get("pending", 0),
            failed=summary.get("failed", 0),
        )
        cfg = self.app.get_server_sync_config()
        if message:
            status_text = message
        elif not cfg.get("enabled"):
            status_text = self.app.t("server_sync_status_disabled")
        elif cfg.get("offline_mode"):
            status_text = self.app.t("server_sync_status_offline")
        elif not str(cfg.get("base_url", "")).strip():
            status_text = self.app.t("server_sync_status_missing_url")
        else:
            status_text = self.app.t("server_sync_status_configured")
        self.server_status.config(
            text=f"{status_text}\n{queue_text}",
            fg=self.colors["success"] if ok else self.colors["text_secondary"],
            bg=self.colors["success_light"] if ok else self.colors["card_soft"],
        )
        if hasattr(self, "server_readiness"):
            try:
                readiness = self.app.get_network_readiness_report(write_report=True)
                checkpoint = self.app.get_checkpoint_health_report(write_report=True)
                policy = readiness.get("policy", {})
                queue = readiness.get("queue", {})
                status = readiness.get("status", "local_ready")
                if status == "ready":
                    title = self.app.t("server_sync_readiness_ready")
                    color = self.colors["success"]
                    bg = self.colors["success_light"]
                elif status == "blocked":
                    title = self.app.t("server_sync_readiness_blocked")
                    color = self.colors["danger"]
                    bg = self.colors["danger_light"]
                else:
                    title = self.app.t("server_sync_readiness_local")
                    color = self.colors["text_secondary"]
                    bg = self.colors["card_soft"]
                policy_text = self.app.t(policy.get("status_key", "server_sync_readiness_policy_ok"))
                checkpoint_text = self.app.t("server_sync_checkpoint_status").format(
                    count=checkpoint.get("checkpoint_count", 0),
                    latest=(checkpoint.get("latest", {}) or {}).get("created_at", "-") or "-",
                )
                maintenance = self.app.get_offline_maintenance_report(write_report=True)
                maintenance_summary = maintenance.get("summary", {}) if isinstance(maintenance, dict) else {}
                maintenance_text = self.app.t("server_sync_maintenance_status").format(
                    status=maintenance.get("status", "OK") if isinstance(maintenance, dict) else "OK",
                    files=maintenance_summary.get("data_files_checked", 0),
                    checkpoints=maintenance_summary.get("checkpoint_count", 0),
                    pending=maintenance_summary.get("sync_pending", 0),
                )
                text = (
                    f"{self.app.t('server_sync_readiness_title')}: {title}\n"
                    f"{self.app.t('server_sync_readiness_policy')}: {policy_text}\n"
                    f"{self.app.t('server_sync_readiness_queue')}: {queue.get('total', 0)} / Pending {queue.get('pending', 0)} / Failed {queue.get('failed', 0)}\n"
                    f"{self.app.t('server_sync_readiness_token_safe')}\n"
                    f"{checkpoint_text}\n"
                    f"{maintenance_text}"
                )
                self.server_readiness.config(text=text, fg=color, bg=bg)
            except Exception:
                pass

    def _build_data(self):
        self.data_title, _ = self._title(self.data_card, "data_section", None)
        body = tk.Frame(self.data_card, bg=self.colors["card"])
        body.pack(fill=tk.BOTH, expand=True, padx=20, pady=(0, 20))
        self.reset_box = self._action_box(body, "reset_notes_menu", "reset_notes_desc_long", self.app.reset_notes, danger=True)
        self.restore_box = self._action_box(body, "restore_default_menu", "restore_demo_desc_long", self.app.restore_demo_data, danger=False)
        self.quick_backup_box = self._action_box(body, "quick_backup_menu", "quick_backup_desc", self.app.quick_backup, danger=False)
        self.export_box = self._action_box(body, "backup_export_menu", "backup_export_desc", self.app.export_backup, danger=False)
        self.diagnostics_box = self._action_box(body, "diagnostics_export_menu", "diagnostics_export_desc", self.app.export_diagnostics, danger=False)
        self.system_health_box = self._action_box(body, "system_health_menu", "system_health_desc", self.app.show_system_health_center, danger=False)
        self.desktop_doctor_box = self._action_box(body, "desktop_doctor_menu", "desktop_doctor_desc", self.app.run_desktop_doctor, danger=False)
        self.desktop_preflight_box = self._action_box(body, "desktop_preflight_menu", "desktop_preflight_desc", self.app.run_desktop_preflight, danger=False)
        self.close_behavior_box = self._action_box(body, "close_behavior_menu", "close_behavior_desc", self.app.show_close_behavior_dialog, danger=False)
        self.tray_test_box = self._action_box(body, "tray_test_menu", "tray_test_desc", self.app.test_tray_icon, danger=False)
        self.tray_status_box = self._action_box(body, "tray_status_menu", "tray_status_desc", self.app.show_tray_status_dialog, danger=False)
        self.icon_generator_box = self._action_box(body, "icon_generator_menu", "icon_generator_desc", self.app.regenerate_icon_assets, danger=False)
        self.icon_cache_box = self._action_box(body, "icon_cache_tool_menu", "icon_cache_tool_desc", self.app.open_icon_cache_tool, danger=False)
        self.import_box = self._action_box(body, "backup_import_menu", "backup_import_desc", self.app.import_backup, danger=False)
        self.repair_box = self._action_box(body, "data_repair_menu", "data_repair_desc", self.repair_data, danger=False)
        self.self_check_box = self._action_box(body, "self_check_menu", "self_check_desc", self.run_self_check, danger=False)
        self.open_data_box = self._action_box(body, "open_data_folder_menu", "open_data_folder_desc", self.open_data_folder, danger=False)
        self.open_latest_build_box = self._action_box(body, "open_latest_build_menu", "open_latest_build_desc", self.app.open_latest_build_folder, danger=False)
        self.build_cleanup_box = self._action_box(body, "build_cleanup_tool_menu", "build_cleanup_tool_desc", self.app.open_build_cleanup_tool, danger=False)
        self.force_exit_box = self._action_box(body, "force_exit_tool_menu", "force_exit_tool_desc", self.app.open_force_exit_tool, danger=True)
        self.exit_app_box = self._action_box(body, "exit_app_menu", "exit_app_desc", self.app.confirm_exit_app, danger=True)
        info = tk.Frame(body, bg=self.colors["card_soft"], highlightthickness=1, highlightbackground=self.colors["border"])
        info.pack(fill=tk.X, pady=(4, 0))
        self.cloud_title = tk.Label(info, text=self.app.t("cloud_feature_title"), font=("Microsoft YaHei UI", 12, "bold"), fg=self.colors["text"], bg=self.colors["card_soft"])
        self.cloud_title.pack(anchor="w", padx=14, pady=(12, 4))
        self.cloud_hint = tk.Label(info, text=self.app.t("cloud_feature_hint"), font=("Microsoft YaHei UI", 9), fg=self.colors["text_secondary"], bg=self.colors["card_soft"], wraplength=315, justify=tk.LEFT)
        self.cloud_hint.pack(anchor="w", padx=14, pady=(0, 12))

    def _action_box(self, parent, title_key, desc_key, command, danger=False):
        bg = self.colors["danger_light"] if danger else self.colors["card_soft"]
        box = tk.Frame(parent, bg=bg, highlightthickness=1, highlightbackground=self.colors["border"])
        box.pack(fill=tk.X, pady=(0, 12))
        title = tk.Label(box, text=self.app.t(title_key), font=("Microsoft YaHei UI", 12, "bold"), fg=self.colors["danger"] if danger else self.colors["text"], bg=bg)
        title.pack(anchor="w", padx=14, pady=(12, 4))
        desc = tk.Label(box, text=self.app.t(desc_key), font=("Microsoft YaHei UI", 9), fg=self.colors["text_secondary"], bg=bg, wraplength=315, justify=tk.LEFT)
        desc.pack(anchor="w", padx=14, pady=(0, 10))
        btn = create_button(box, self.app.t(title_key), command, self.colors, filled=not danger)
        btn.pack(anchor="w", padx=14, pady=(0, 14))
        return {"title": title, "desc": desc, "btn": btn, "title_key": title_key, "desc_key": desc_key}

    def open_data_folder(self):
        try:
            DATA_DIR.mkdir(parents=True, exist_ok=True)
            if sys.platform.startswith("win"):
                os.startfile(str(DATA_DIR))
            elif sys.platform == "darwin":
                subprocess.Popen(["open", str(DATA_DIR)])
            else:
                subprocess.Popen(["xdg-open", str(DATA_DIR)])
            self.app.set_status("status_ready")
        except Exception as exc:
            messagebox.showwarning(self.app.t("warning_title"), str(exc))

    def run_self_check(self):
        checks = []
        def add(name, ok, detail=""):
            checks.append((name, ok, detail))
        try:
            add(self.app.t("self_check_python"), True, sys.version.split()[0])
        except Exception as exc:
            add(self.app.t("self_check_python"), False, str(exc))
        try:
            add(self.app.t("self_check_documents"), isinstance(getattr(self.app, "documents", None), dict), str(len(getattr(self.app, "documents", {}) or {})))
        except Exception as exc:
            add(self.app.t("self_check_documents"), False, str(exc))
        try:
            add(self.app.t("self_check_notes"), isinstance(getattr(self.app, "notes", None), dict), str(len(getattr(self.app, "notes", {}) or {})))
        except Exception as exc:
            add(self.app.t("self_check_notes"), False, str(exc))
        try:
            todos = getattr(self.app, "todos", {})
            add(self.app.t("self_check_tasks"), isinstance(todos, dict) and isinstance(todos.get("items", []), list), str(len(todos.get("items", []))))
        except Exception as exc:
            add(self.app.t("self_check_tasks"), False, str(exc))
        try:
            DATA_DIR.mkdir(parents=True, exist_ok=True)
            add(self.app.t("self_check_data_dir"), DATA_DIR.exists(), str(DATA_DIR))
        except Exception as exc:
            add(self.app.t("self_check_data_dir"), False, str(exc))
        try:
            add(self.app.t("self_check_dpi"), True, f"{self.app.root.winfo_screenwidth()}x{self.app.root.winfo_screenheight()} / scale {getattr(self.app, 'font_scale', 1.0):.2f}")
        except Exception as exc:
            add(self.app.t("self_check_dpi"), False, str(exc))
        try:
            tray = getattr(self.app, "check_tray_backend", lambda: {"ok": False, "error": "missing"})()
            detail = tray.get("backend") or tray.get("error") or "pystray"
            add(self.app.t("self_check_tray"), bool(tray.get("ok")), detail)
        except Exception as exc:
            add(self.app.t("self_check_tray"), False, str(exc))
        try:
            icon = getattr(self.app, "icon_status_summary", lambda: {"ico_sizes": [], "png_sizes": []})()
            detail = f"ico={len(icon.get('ico_sizes', []))} png={len(icon.get('png_sizes', []))} verify={icon.get('verify_tool_exists')}"
            add(self.app.t("self_check_icon"), bool(icon.get("ico_exists")), detail)
        except Exception as exc:
            add(self.app.t("self_check_icon"), False, str(exc))
        ok_count = sum(1 for _, ok, _ in checks if ok)
        lines = [self.app.t("self_check_summary").format(ok=ok_count, total=len(checks)), ""]
        for name, ok, detail in checks:
            lines.append(("✅ " if ok else "⚠️ ") + f"{name}: {detail}")
        messagebox.showinfo(self.app.t("self_check_menu"), "\n".join(lines))

    def repair_data(self):
        fixed = 0
        removed = 0
        now = getattr(self.app, "today_key", lambda: "")()

        docs = getattr(self.app, "documents", {})
        if not isinstance(docs, dict):
            self.app.documents = {}
            docs = self.app.documents
            fixed += 1
        for doc_id, doc in list(docs.items()):
            if not isinstance(doc, dict):
                docs.pop(doc_id, None)
                removed += 1
                continue
            if doc.get("type") not in ("doc", "sheet"):
                doc["type"] = "sheet" if "sheet" in doc else "doc"
                fixed += 1
            if not str(doc.get("title", "")).strip():
                doc["title"] = self.app.t("shared_untitled_sheet") if doc.get("type") == "sheet" else self.app.t("shared_untitled_doc")
                fixed += 1
            if doc.get("type") == "sheet":
                if not isinstance(doc.get("sheet"), list) or not doc.get("sheet"):
                    doc["sheet"] = [["" for _ in range(8)] for _ in range(12)]
                    fixed += 1
                doc.setdefault("content", "")
            else:
                if not isinstance(doc.get("content"), str):
                    doc["content"] = str(doc.get("content", ""))
                    fixed += 1
            if doc.get("scope") not in ("personal", "enterprise"):
                doc["scope"] = "enterprise"
                fixed += 1
            doc.setdefault("owner", self.app.user_settings.get("username") or "Local")
            doc.setdefault("shared", True)
            doc.setdefault("updated", now)
        save_documents(docs)

        todos = getattr(self.app, "todos", {})
        if not isinstance(todos, dict):
            todos = {"items": []}
            self.app.todos = todos
            fixed += 1
        items = todos.setdefault("items", [])
        if not isinstance(items, list):
            todos["items"] = []
            fixed += 1
        else:
            clean_items = []
            for item in items:
                if isinstance(item, dict) and str(item.get("text", "")).strip():
                    item["done"] = bool(item.get("done"))
                    clean_items.append(item)
                else:
                    removed += 1
            todos["items"] = clean_items
        save_todos(todos)

        enterprise = getattr(self.app, "enterprise", {})
        if not isinstance(enterprise, dict):
            enterprise = {}
            self.app.enterprise = enterprise
            fixed += 1
        enterprise.setdefault("employees", [])
        enterprise.setdefault("notifications", [])
        enterprise.setdefault("goals", [])
        enterprise.setdefault("last_sync", "")
        enterprise.setdefault("company_name", "")
        if enterprise.get("company_name") and not enterprise.get("company_invite_code"):
            try:
                import random, string
                enterprise["company_invite_code"] = "NX-" + "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
                fixed += 1
            except Exception:
                pass
        save_enterprise(enterprise)

        logs = getattr(self.app, "action_logs", {})
        if not isinstance(logs, dict):
            logs = {"items": []}
            self.app.action_logs = logs
            fixed += 1
        logs["items"] = [item for item in logs.get("items", []) if isinstance(item, dict)][-300:]
        save_action_logs(logs)

        self.app.refresh_home()
        if getattr(self.app, "current_page", "") in self.app.pages:
            page = self.app.pages.get(self.app.current_page)
            if page and hasattr(page, "refresh"):
                try:
                    page.refresh()
                except Exception:
                    pass
        self._render_action_logs()
        messagebox.showinfo(self.app.t("success_title"), self.app.t("data_repair_done").format(fixed=fixed, removed=removed))

    def _accounts(self):
        return self.app.user_settings.setdefault("accounts", [])

    def create_account(self):
        username = self.username_entry.get().strip()
        password = self.password_entry.get().strip()
        confirm = self.confirm_entry.get().strip()
        if not username:
            messagebox.showwarning(self.app.t("confirm_title"), self.app.t("username_placeholder"))
            return
        if not password:
            messagebox.showwarning(self.app.t("confirm_title"), self.app.t("password_required"))
            return
        if password != confirm:
            messagebox.showwarning(self.app.t("confirm_title"), self.app.t("password_mismatch"))
            return
        if any(acc.get("username") == username for acc in self._accounts()):
            messagebox.showwarning(self.app.t("confirm_title"), self.app.t("account_exists"))
            return
        role = self.role_var.get()
        account = {"username": username, "password": password, "role": role, "created": True}
        if hasattr(self.app, "_ensure_account_puid"):
            self.app._ensure_account_puid(account, username)
        self._accounts().append(account)
        self.app.user_settings["username"] = username
        self.app.user_settings["role"] = role
        self.app.user_settings["puid"] = account.get("puid", self.app.user_settings.get("puid", ""))
        self.app.user_settings["logged_in"] = True
        save_settings(self.app.user_settings)
        self._refresh_login_status()
        self.app.refresh_user_state()
        self.app.set_status("account_created")
        messagebox.showinfo(self.app.t("success_title"), self.app.t("account_created"))

    def login(self):
        username = self.username_entry.get().strip()
        password = self.password_entry.get().strip()
        accounts = self._accounts()
        role = self.role_var.get()
        if accounts:
            matched = next((acc for acc in accounts if acc.get("username") == username and acc.get("password") == password), None)
            if not matched:
                messagebox.showwarning(self.app.t("confirm_title"), self.app.t("login_failed"))
                return
            role = matched.get("role", "user")
            if hasattr(self.app, "_ensure_account_puid"):
                self.app._ensure_account_puid(matched, username)
        self.app.user_settings["username"] = username or self.app.t("username_placeholder")
        self.app.user_settings["role"] = role
        if accounts:
            matched_account = next((acc for acc in accounts if acc.get("username") == username), None)
            if matched_account:
                self.app.user_settings["puid"] = matched_account.get("puid", self.app.user_settings.get("puid", ""))
        self.app.user_settings["logged_in"] = True
        save_settings(self.app.user_settings)
        self._refresh_login_status()
        self.app.refresh_user_state()
        self.app.set_status("profile_saved")

    def logout(self):
        self.app.user_settings["logged_in"] = False
        save_settings(self.app.user_settings)
        self._refresh_login_status()
        self.app.refresh_user_state()
        self.app.set_status("profile_saved")
        try:
            self.app.logout_to_login()
        except Exception:
            pass

    def refresh(self):
        self.username_entry.delete(0, tk.END)
        self.username_entry.insert(0, self.app.user_settings.get("username", ""))
        self._refresh_login_status()
        self._refresh_lang_buttons()
        if hasattr(self, "font_scale_var"):
            value = int(round(float(self.app.user_settings.get("font_scale", 1.0)) * 100))
            self.font_scale_var.set(max(95, min(125, value)))
            self._update_font_preview()
        for key, var in self.quick_vars.items():
            var.set(self.app.get_quick_actions().get(key, True))
        if hasattr(self, "performance_tier_var"):
            self.performance_tier_var.set(self._performance_tier_label(self.app.user_settings.get("performance_tier", "auto") or "auto"))
        if hasattr(self, "smooth_restore_var"):
            self.smooth_restore_var.set(bool(self.app.user_settings.get("smooth_restore", True)))
        if hasattr(self, "restore_full_cover_var"):
            self.restore_full_cover_var.set(bool(self.app.user_settings.get("restore_full_window_cover", True)))
        if hasattr(self, "light_switch_var"):
            self.light_switch_var.set(bool(self.app.user_settings.get("lightweight_page_switch", True)))
        if hasattr(self, "close_to_tray_var"):
            self.close_to_tray_var.set(bool(self.app.user_settings.get("close_to_tray", True)))
        if hasattr(self, "source_mode_close_direct_var"):
            self.source_mode_close_direct_var.set(bool(self.app.user_settings.get("source_mode_close_direct", True)))
        if hasattr(self, "source_mode_force_os_exit_var"):
            self.source_mode_force_os_exit_var.set(bool(self.app.user_settings.get("source_mode_force_os_exit", True)))
        if hasattr(self, "performance_profile_label"):
            self.performance_profile_label.config(text=self._performance_profile_text())
        if hasattr(self, "performance_auto_btn"):
            self.performance_auto_btn.config(text=self.app.t("performance_preset_auto"))
        if hasattr(self, "performance_balanced_btn"):
            self.performance_balanced_btn.config(text=self.app.t("performance_preset_balanced"))
        if hasattr(self, "performance_low_btn"):
            self.performance_low_btn.config(text=self.app.t("performance_preset_low_power"))
        if hasattr(self, "server_enabled_var"):
            cfg = self.app.get_server_sync_config()
            self.server_enabled_var.set(bool(cfg.get("enabled", False)))
            self.server_offline_var.set(bool(cfg.get("offline_mode", True)))
            self._refresh_server_status()
        reminders = self.app.get_holiday_reminders()
        self.holiday_vars["china"].set(reminders.get("china", True))
        self.holiday_vars["indonesia"].set(reminders.get("indonesia", True))
        self.days_var.set(int(reminders.get("days_before", 1)))
        self._render_action_logs()

    def update_language(self):
        self.account_title.config(text=self.app.t("login_title"))
        self.account_hint.config(text=self.app.t("login_hint"))
        self.username_label.config(text=self.app.t("username_label"))
        self.password_label.config(text=self.app.t("account_password"))
        self.confirm_label.config(text=self.app.t("account_confirm_password"))
        self.role_label.config(text=self.app.t("account_role"))
        self.role_user.config(text=self.app.t("normal_staff"))
        self.role_admin.config(text=self.app.t("admin_badge"))
        self.login_btn.config(text=self.app.t("login_btn"))
        self.create_btn.config(text=self.app.t("create_account"))
        self.logout_btn.config(text=self.app.t("logout_btn"))
        if hasattr(self, "mode_title"):
            self.mode_title.config(text=self.app.t("mode_section"))
        if hasattr(self, "mode_hint") and self.mode_hint:
            self.mode_hint.config(text=self.app.t("mode_hint"))
        self._update_mode_buttons()
        self.language_title.config(text=self.app.t("language_section"))
        self.language_hint.config(text=self.app.t("language_hint"))
        if hasattr(self, "font_title"):
            self.font_title.config(text=self.app.t("font_ui_section"))
        if hasattr(self, "font_hint") and self.font_hint:
            self.font_hint.config(text=self.app.t("font_ui_hint"))
        if hasattr(self, "font_scale_label"):
            self.font_scale_label.config(text=self.app.t("font_ui_scale_label"))
        if hasattr(self, "font_preview"):
            self.font_preview.config(text=self.app.t("font_ui_preview_text"))
        if hasattr(self, "font_apply_btn"):
            self.font_apply_btn.config(text=self.app.t("font_apply_btn"))
        if hasattr(self, "performance_title"):
            self.performance_title.config(text=self.app.t("performance_section"))
        if hasattr(self, "performance_hint") and self.performance_hint:
            self.performance_hint.config(text=self.app.t("performance_hint"))
        if hasattr(self, "smooth_restore_check"):
            self.smooth_restore_check.config(text=self.app.t("performance_smooth_restore"))
        if hasattr(self, "smooth_restore_desc"):
            self.smooth_restore_desc.config(text=self.app.t("performance_smooth_restore_desc"))
        if hasattr(self, "restore_full_cover_check"):
            self.restore_full_cover_check.config(text=self.app.t("performance_restore_full_cover"))
        if hasattr(self, "restore_full_cover_desc"):
            self.restore_full_cover_desc.config(text=self.app.t("performance_restore_full_cover_desc"))
        if hasattr(self, "light_switch_check"):
            self.light_switch_check.config(text=self.app.t("performance_light_switch"))
        if hasattr(self, "light_switch_desc"):
            self.light_switch_desc.config(text=self.app.t("performance_light_switch_desc"))
        if hasattr(self, "close_to_tray_check"):
            self.close_to_tray_check.config(text=self.app.t("performance_close_to_tray"))
        if hasattr(self, "close_to_tray_desc"):
            self.close_to_tray_desc.config(text=self.app.t("performance_close_to_tray_desc"))
        if hasattr(self, "source_mode_close_direct_check"):
            self.source_mode_close_direct_check.config(text=self.app.t("performance_source_close_direct"))
        if hasattr(self, "source_mode_close_direct_desc"):
            self.source_mode_close_direct_desc.config(text=self.app.t("performance_source_close_direct_desc"))
        if hasattr(self, "source_mode_force_os_exit_check"):
            self.source_mode_force_os_exit_check.config(text=self.app.t("performance_source_force_exit"))
        if hasattr(self, "source_mode_force_os_exit_desc"):
            self.source_mode_force_os_exit_desc.config(text=self.app.t("performance_source_force_exit_desc"))
        if hasattr(self, "server_title"):
            self.server_title.config(text=self.app.t("server_sync_section"))
        if hasattr(self, "server_hint") and self.server_hint:
            self.server_hint.config(text=self.app.t("server_sync_hint"))
        if hasattr(self, "server_managed_label"):
            self.server_managed_label.config(text=self.app.t("server_sync_system_managed"))
        if hasattr(self, "server_managed_hint"):
            self.server_managed_hint.config(text=self.app.t("server_sync_user_locked"))
        if hasattr(self, "server_enabled_check"):
            self.server_enabled_check.config(text=self.app.t("server_sync_enable"))
        if hasattr(self, "server_offline_check"):
            self.server_offline_check.config(text=self.app.t("server_sync_offline_mode"))
        if hasattr(self, "server_url_label"):
            self.server_url_label.config(text=self.app.t("server_sync_base_url"))
        if hasattr(self, "server_workspace_label"):
            self.server_workspace_label.config(text=self.app.t("server_sync_workspace_id"))
        if hasattr(self, "server_token_label"):
            self.server_token_label.config(text=self.app.t("server_sync_api_token"))
        if hasattr(self, "server_retry_label"):
            self.server_retry_label.config(text=self.app.t("server_sync_retry_count"))
        if hasattr(self, "server_audit_hint"):
            self.server_audit_hint.config(text=self.app.t("server_sync_network_audit_hint"))
        if hasattr(self, "server_source_label"):
            self.server_source_label.config(text=self._server_source_text())
        if hasattr(self, "server_save_btn"):
            self.server_save_btn.config(text=self.app.t("server_sync_save"))
        if hasattr(self, "server_test_btn"):
            self.server_test_btn.config(text=self.app.t("server_sync_test"))
        if hasattr(self, "server_snapshot_btn"):
            self.server_snapshot_btn.config(text=self.app.t("server_sync_prepare_snapshot"))
        if hasattr(self, "server_status"):
            self._refresh_server_status()
        if hasattr(self, "theme_title"):
            self.theme_title.config(text=self.app.t("theme_title"))
        if hasattr(self, "theme_hint") and self.theme_hint:
            self.theme_hint.config(text=self.app.t("theme_hint"))
        if hasattr(self, "theme_buttons"):
            for theme_id, btn in self.theme_buttons.items():
                btn.config(text=self.app.t(THEME_PRESETS.get(theme_id, {}).get("name_key", theme_id)))
        self.quick_title.config(text=self.app.t("quick_settings_title"))
        self.quick_hint.config(text=self.app.t("quick_modules_hint"))
        for cb, text_key in self.quick_checks.values():
            cb.config(text=self.app.t(text_key))
        self.holiday_title.config(text=self.app.t("holiday_reminder_section"))
        self.holiday_hint.config(text=self.app.t("holiday_reminder_hint"))
        self.china_holiday_cb.config(text=self.app.t("holiday_remind_china"))
        self.indonesia_holiday_cb.config(text=self.app.t("holiday_remind_indonesia"))
        self.days_label.config(text=self.app.t("holiday_remind_days"))
        self.log_title.config(text=self.app.t("action_log_title"))
        self.log_hint.config(text=self.app.t("action_log_hint"))
        self.log_clear_btn.config(text=self.app.t("action_log_clear"))
        if hasattr(self, "log_open_all_btn"):
            self.log_open_all_btn.config(text=self.app.t("action_log_open_all"))
        self._render_action_logs()
        self.data_title.config(text=self.app.t("data_section"))
        self.cloud_title.config(text=self.app.t("cloud_feature_title"))
        self.cloud_hint.config(text=self.app.t("cloud_feature_hint"))
        for action in [self.reset_box, self.restore_box, getattr(self, "quick_backup_box", None), getattr(self, "export_box", None), getattr(self, "diagnostics_box", None), getattr(self, "system_health_box", None), getattr(self, "desktop_doctor_box", None), getattr(self, "desktop_preflight_box", None), getattr(self, "close_behavior_box", None), getattr(self, "tray_test_box", None), getattr(self, "tray_status_box", None), getattr(self, "icon_generator_box", None), getattr(self, "icon_cache_box", None), getattr(self, "import_box", None), getattr(self, "repair_box", None), getattr(self, "self_check_box", None), getattr(self, "open_data_box", None), getattr(self, "open_latest_build_box", None), getattr(self, "build_cleanup_box", None), getattr(self, "force_exit_box", None), getattr(self, "exit_app_box", None)]:
            if not action:
                continue
            action["title"].config(text=self.app.t(action["title_key"]))
            action["desc"].config(text=self.app.t(action["desc_key"]))
            action["btn"].config(text=self.app.t(action["title_key"]))
        self.refresh()

    def _refresh_login_status(self):
        if self.app.user_settings.get("logged_in") and self.app.user_settings.get("username"):
            role = self.app.t("admin_badge") if self.app.user_settings.get("role") == "admin" else self.app.t("normal_staff")
            self.login_status.config(text=f"{self.app.t('logged_in_as')} {self.app.user_settings.get('username')} · {role}", fg=self.colors["success"], bg=self.colors["success_light"])
        else:
            self.login_status.config(text=self.app.t("not_logged_in"), fg=self.colors["text_secondary"], bg=self.colors["bg"])

    def _refresh_lang_buttons(self):
        for code, btn in self.lang_buttons.items():
            active = code == self.app.lang_code
            btn.config(bg=self.colors["primary"] if active else self.colors["card_soft"], fg="white" if active else self.colors["text"], activebackground=self.colors["primary_dark"] if active else self.colors["primary_light"], activeforeground="white" if active else self.colors["primary"])
