import json
import os
import shutil
import subprocess
import time
from pathlib import Path

import gi

gi.require_version("Gtk", "3.0")
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.entry import Entry
from fabric.widgets.image import Image as FabricImage
from fabric.widgets.label import Label
from fabric.widgets.scale import Scale
from fabric.widgets.scrolledwindow import ScrolledWindow
from fabric.widgets.stack import Stack
from fabric.widgets.window import Window
from gi.repository import GdkPixbuf, GLib, Gtk
from PIL import Image

from .data import (
    APP_NAME,
    APP_NAME_CAP,
)
from .settings_utils import (
    backup_and_replace,
    bind_vars,
    get_bind_var,
    get_default,
    start_config,
)


class HyprConfGUI(Window):
    def __init__(self, show_lock_checkbox: bool, show_idle_checkbox: bool, **kwargs):
        super().__init__(
            title="Ax-Shell Settings",
            name="axshell-settings-window",
            size=(640, 640),
            **kwargs,
        )

        self.set_resizable(False)

        self.selected_face_icon = None
        self.show_lock_checkbox = show_lock_checkbox
        self.show_idle_checkbox = show_idle_checkbox

        root_box = Box(orientation="v", spacing=10, style="margin: 10px;")
        self.add(root_box)

        main_content_box = Box(orientation="h", spacing=6, v_expand=True, h_expand=True)
        root_box.add(main_content_box)

        self.tab_stack = Stack(
            transition_type="slide-up-down",
            transition_duration=250,
            v_expand=True,
            h_expand=True,
        )

        self.key_bindings_tab_content = self.create_key_bindings_tab()
        self.appearance_tab_content = self.create_appearance_tab()
        self.system_tab_content = self.create_system_tab()
        self.about_tab_content = self.create_about_tab()

        self.tab_stack.add_titled(
            self.key_bindings_tab_content, "key_bindings", "Key Bindings"
        )
        self.tab_stack.add_titled(
            self.appearance_tab_content, "appearance", "Appearance"
        )
        self.tab_stack.add_titled(self.system_tab_content, "system", "System")
        self.tab_stack.add_titled(self.about_tab_content, "about", "About")

        tab_switcher = Gtk.StackSwitcher()
        tab_switcher.set_stack(self.tab_stack)
        tab_switcher.set_orientation(Gtk.Orientation.VERTICAL)
        main_content_box.add(tab_switcher)
        main_content_box.add(self.tab_stack)

        button_box = Box(orientation="h", spacing=10, h_align="end")
        reset_btn = Button(label="Reset to Defaults", on_clicked=self.on_reset)
        button_box.add(reset_btn)
        close_btn = Button(label="Close", on_clicked=self.on_close)
        button_box.add(close_btn)
        accept_btn = Button(label="Apply & Reload", on_clicked=self.on_accept)
        button_box.add(accept_btn)
        root_box.add(button_box)

    def create_key_bindings_tab(self):
        scrolled_window = ScrolledWindow(
            h_scrollbar_policy="never",
            v_scrollbar_policy="automatic",
            h_expand=True,
            v_expand=True,
            propagate_width=False,
            propagate_height=False,
        )

        main_vbox = Box(orientation="v", spacing=10, style="margin: 15px;")
        scrolled_window.add(main_vbox)

        keybind_grid = Gtk.Grid()
        keybind_grid.set_column_spacing(10)
        keybind_grid.set_row_spacing(8)
        keybind_grid.set_margin_start(5)
        keybind_grid.set_margin_end(5)
        keybind_grid.set_margin_top(5)
        keybind_grid.set_margin_bottom(5)

        action_label = Label(
            markup="<b>Action</b>", h_align="start", style="margin-bottom: 5px;"
        )
        modifier_label = Label(
            markup="<b>Modifier</b>", h_align="start", style="margin-bottom: 5px;"
        )
        separator_label = Label(
            label="+", h_align="center", style="margin-bottom: 5px;"
        )
        key_label = Label(
            markup="<b>Key</b>", h_align="start", style="margin-bottom: 5px;"
        )

        keybind_grid.attach(action_label, 0, 0, 1, 1)
        keybind_grid.attach(modifier_label, 1, 0, 1, 1)
        keybind_grid.attach(separator_label, 2, 0, 1, 1)
        keybind_grid.attach(key_label, 3, 0, 1, 1)

        self.entries = []
        bindings = [
            (f"Reload {APP_NAME_CAP}", "prefix_restart", "suffix_restart"),
            ("Message", "prefix_axmsg", "suffix_axmsg"),
            ("Dashboard", "prefix_dash", "suffix_dash"),
            ("Bluetooth", "prefix_bluetooth", "suffix_bluetooth"),
            ("Pins", "prefix_pins", "suffix_pins"),
            ("Kanban", "prefix_kanban", "suffix_kanban"),
            ("App Launcher", "prefix_launcher", "suffix_launcher"),
            ("Tmux", "prefix_tmux", "suffix_tmux"),
            ("Clipboard History", "prefix_cliphist", "suffix_cliphist"),
            ("Toolbox", "prefix_toolbox", "suffix_toolbox"),
            ("Overview", "prefix_overview", "suffix_overview"),
            ("Wallpapers", "prefix_wallpapers", "suffix_wallpapers"),
            ("Random Wallpaper", "prefix_randwall", "suffix_randwall"),
            ("Audio Mixer", "prefix_mixer", "suffix_mixer"),
            ("Emoji Picker", "prefix_emoji", "suffix_emoji"),
            ("Power Menu", "prefix_power", "suffix_power"),
            ("Toggle Caffeine", "prefix_caffeine", "suffix_caffeine"),
            ("Toggle Bar", "prefix_toggle", "suffix_toggle"),
            ("Reload CSS", "prefix_css", "suffix_css"),
            (
                "Restart with inspector",
                "prefix_restart_inspector",
                "suffix_restart_inspector",
            ),
        ]

        for i, (label_text, prefix_key, suffix_key) in enumerate(bindings):
            row = i + 1
            binding_label = Label(label=label_text, h_align="start")
            keybind_grid.attach(binding_label, 0, row, 1, 1)
            prefix_entry = Entry(text=get_bind_var(prefix_key))
            keybind_grid.attach(prefix_entry, 1, row, 1, 1)
            plus_label = Label(label="+", h_align="center")
            keybind_grid.attach(plus_label, 2, row, 1, 1)
            suffix_entry = Entry(text=get_bind_var(suffix_key))
            keybind_grid.attach(suffix_entry, 3, row, 1, 1)
            self.entries.append((prefix_key, suffix_key, prefix_entry, suffix_entry))

        main_vbox.add(keybind_grid)
        return scrolled_window

    def create_appearance_tab(self):
        scrolled_window = ScrolledWindow(
            h_scrollbar_policy="never",
            v_scrollbar_policy="automatic",
            h_expand=True,
            v_expand=True,
            propagate_width=False,
            propagate_height=False,
        )

        vbox = Box(orientation="v", spacing=15, style="margin: 15px;")
        scrolled_window.add(vbox)

        top_grid = Gtk.Grid()
        top_grid.set_column_spacing(20)
        top_grid.set_row_spacing(5)
        top_grid.set_margin_bottom(10)
        vbox.add(top_grid)

        wall_header = Label(markup="<b>Wallpapers</b>", h_align="start")
        top_grid.attach(wall_header, 0, 0, 1, 1)
        wall_label = Label(label="Directory:", h_align="start", v_align="center")
        top_grid.attach(wall_label, 0, 1, 1, 1)

        chooser_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        chooser_container.set_halign(Gtk.Align.START)
        chooser_container.set_valign(Gtk.Align.CENTER)
        self.wall_dir_chooser = Gtk.FileChooserButton(
            title="Select a folder", action=Gtk.FileChooserAction.SELECT_FOLDER
        )
        self.wall_dir_chooser.set_tooltip_text(
            "Select the directory containing your wallpaper images"
        )
        self.wall_dir_chooser.set_filename(get_bind_var("wallpapers_dir"))
        self.wall_dir_chooser.set_size_request(180, -1)
        chooser_container.add(self.wall_dir_chooser)
        top_grid.attach(chooser_container, 1, 1, 1, 1)

        face_header = Label(markup="<b>Profile Icon</b>", h_align="start")
        top_grid.attach(face_header, 2, 0, 2, 1)
        current_face = os.path.expanduser("~/.face.icon")
        face_image_container = Box(
            style_classes=["image-frame"], h_align="center", v_align="center"
        )
        self.face_image = FabricImage(size=64)
        try:
            if os.path.exists(current_face):
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(current_face, 64, 64)
                self.face_image.set_from_pixbuf(pixbuf)
            else:
                self.face_image.set_from_icon_name("user-info", Gtk.IconSize.DIALOG)
        except Exception as e:
            print(f"Error loading face icon: {e}")
            self.face_image.set_from_icon_name("image-missing", Gtk.IconSize.DIALOG)
        face_image_container.add(self.face_image)
        top_grid.attach(face_image_container, 2, 1, 1, 1)

        browse_btn_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        browse_btn_container.set_halign(Gtk.Align.START)
        browse_btn_container.set_valign(Gtk.Align.CENTER)
        face_btn = Button(
            label="Browse...",
            tooltip_text="Select a square image for your profile icon",
            on_clicked=self.on_select_face_icon,
        )
        browse_btn_container.add(face_btn)
        top_grid.attach(browse_btn_container, 3, 1, 1, 1)
        self.face_status_label = Label(label="", h_align="start")
        top_grid.attach(self.face_status_label, 2, 2, 2, 1)

        separator1 = Box(
            style="min-height: 1px; background-color: alpha(@fg_color, 0.2); margin: 5px 0px;",
            h_expand=True,
        )
        vbox.add(separator1)

        # START NEW SECTION FOR DATETIME FORMAT
        datetime_format_header = Label(
            markup="<b>Date & Time Format</b>", h_align="start"
        )
        vbox.add(datetime_format_header)

        datetime_grid = Gtk.Grid()
        datetime_grid.set_column_spacing(20)
        datetime_grid.set_row_spacing(10)
        datetime_grid.set_margin_start(10)
        datetime_grid.set_margin_top(5)
        datetime_grid.set_margin_bottom(10)  # Adds space before the next section
        vbox.add(datetime_grid)

        datetime_12h_label = Label(
            label="Use 12-Hour Clock", h_align="start", v_align="center"
        )
        datetime_grid.attach(datetime_12h_label, 0, 0, 1, 1)

        datetime_12h_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.datetime_12h_switch = Gtk.Switch(
            active=get_bind_var("datetime_12h_format")
        )
        datetime_12h_switch_container.add(self.datetime_12h_switch)
        datetime_grid.attach(datetime_12h_switch_container, 1, 0, 1, 1)
        # END NEW SECTION FOR DATETIME FORMAT

        layout_header = Label(markup="<b>Layout Options</b>", h_align="start")
        vbox.add(layout_header)
        layout_grid = Gtk.Grid()
        layout_grid.set_column_spacing(20)
        layout_grid.set_row_spacing(10)
        layout_grid.set_margin_start(10)
        layout_grid.set_margin_top(5)
        vbox.add(layout_grid)

        position_label = Label(label="Bar Position", h_align="start", v_align="center")
        layout_grid.attach(position_label, 0, 0, 1, 1)
        position_combo_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.position_combo = Gtk.ComboBoxText()
        self.position_combo.set_tooltip_text("Select the position of the bar")
        positions = ["Top", "Bottom", "Left", "Right"]
        for pos in positions:
            self.position_combo.append_text(pos)
        current_position = get_bind_var("bar_position")
        try:
            self.position_combo.set_active(positions.index(current_position))
        except ValueError:
            self.position_combo.set_active(0)
        self.position_combo.connect("changed", self.on_position_changed)
        position_combo_container.add(self.position_combo)
        layout_grid.attach(position_combo_container, 1, 0, 1, 1)

        centered_label = Label(
            label="Centered Bar (Left/Right Only)", h_align="start", v_align="center"
        )
        layout_grid.attach(centered_label, 2, 0, 1, 1)
        centered_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.centered_switch = Gtk.Switch(
            active=get_bind_var("centered_bar"),
            sensitive=get_bind_var("bar_position") in ["Left", "Right"],
        )
        centered_switch_container.add(self.centered_switch)
        layout_grid.attach(centered_switch_container, 3, 0, 1, 1)

        dock_label = Label(label="Show Dock", h_align="start", v_align="center")
        layout_grid.attach(dock_label, 0, 1, 1, 1)
        dock_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.dock_switch = Gtk.Switch(active=get_bind_var("dock_enabled"))
        self.dock_switch.connect("notify::active", self.on_dock_enabled_changed)
        dock_switch_container.add(self.dock_switch)
        layout_grid.attach(dock_switch_container, 1, 1, 1, 1)

        dock_hover_label = Label(
            label="Always Show Dock", h_align="start", v_align="center"
        )
        layout_grid.attach(dock_hover_label, 2, 1, 1, 1)
        dock_hover_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.dock_hover_switch = Gtk.Switch(
            active=get_bind_var("dock_always_show"),
            sensitive=self.dock_switch.get_active(),
        )
        dock_hover_switch_container.add(self.dock_hover_switch)
        layout_grid.attach(dock_hover_switch_container, 3, 1, 1, 1)

        dock_size_label = Label(
            label="Dock Icon Size", h_align="start", v_align="center"
        )
        layout_grid.attach(dock_size_label, 0, 2, 1, 1)
        self.dock_size_scale = Scale(
            min_value=16,
            max_value=48,
            value=get_bind_var("dock_icon_size"),
            increments=(2, 4),
            draw_value=True,
            value_position="right",
            digits=0,
            h_expand=True,
        )
        layout_grid.attach(self.dock_size_scale, 1, 2, 3, 1)

        ws_num_label = Label(
            label="Show Workspace Numbers", h_align="start", v_align="center"
        )
        layout_grid.attach(ws_num_label, 0, 3, 1, 1)
        ws_num_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.ws_num_switch = Gtk.Switch(
            active=get_bind_var("bar_workspace_show_number")
        )
        self.ws_num_switch.connect("notify::active", self.on_ws_num_changed)
        ws_num_switch_container.add(self.ws_num_switch)
        layout_grid.attach(ws_num_switch_container, 1, 3, 1, 1)

        ws_chinese_label = Label(
            label="Use Chinese Numerals", h_align="start", v_align="center"
        )
        layout_grid.attach(ws_chinese_label, 2, 3, 1, 1)
        ws_chinese_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.ws_chinese_switch = Gtk.Switch(
            active=get_bind_var("bar_workspace_use_chinese_numerals"),
            sensitive=self.ws_num_switch.get_active(),
        )
        ws_chinese_switch_container.add(self.ws_chinese_switch)
        layout_grid.attach(ws_chinese_switch_container, 3, 3, 1, 1)

        special_ws_label = Label(
            label="Hide Special Workspace", h_align="start", v_align="center"
        )
        layout_grid.attach(special_ws_label, 0, 4, 1, 1)
        special_ws_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.special_ws_switch = Gtk.Switch(
            active=get_bind_var("bar_hide_special_workspace")
        )
        special_ws_switch_container.add(self.special_ws_switch)
        layout_grid.attach(special_ws_switch_container, 1, 4, 1, 1)

        bar_theme_label = Label(label="Bar Theme", h_align="start", v_align="center")
        layout_grid.attach(bar_theme_label, 0, 5, 1, 1)
        bar_theme_combo_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.bar_theme_combo = Gtk.ComboBoxText()
        self.bar_theme_combo.set_tooltip_text("Select the visual theme for the bar")
        themes = ["Pills", "Dense", "Edge"]
        for theme in themes:
            self.bar_theme_combo.append_text(theme)
        current_theme = get_bind_var("bar_theme")
        try:
            self.bar_theme_combo.set_active(themes.index(current_theme))
        except ValueError:
            self.bar_theme_combo.set_active(0)
        bar_theme_combo_container.add(self.bar_theme_combo)
        layout_grid.attach(bar_theme_combo_container, 1, 5, 3, 1)

        dock_theme_label = Label(label="Dock Theme", h_align="start", v_align="center")
        layout_grid.attach(dock_theme_label, 0, 6, 1, 1)
        dock_theme_combo_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.dock_theme_combo = Gtk.ComboBoxText()
        self.dock_theme_combo.set_tooltip_text("Select the visual theme for the dock")
        for theme in themes:
            self.dock_theme_combo.append_text(theme)
        current_dock_theme = get_bind_var("dock_theme")
        try:
            self.dock_theme_combo.set_active(themes.index(current_dock_theme))
        except ValueError:
            self.dock_theme_combo.set_active(0)
        dock_theme_combo_container.add(self.dock_theme_combo)
        layout_grid.attach(dock_theme_combo_container, 1, 6, 3, 1)

        panel_theme_label = Label(
            label="Panel Theme", h_align="start", v_align="center"
        )
        layout_grid.attach(panel_theme_label, 0, 7, 1, 1)
        panel_theme_combo_container = Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.panel_theme_combo = Gtk.ComboBoxText()
        self.panel_theme_combo.set_tooltip_text(
            "Select the theme/mode for panels like toolbox, clipboard, etc."
        )
        panel_themes = ["Notch", "Panel"]
        for theme in panel_themes:
            self.panel_theme_combo.append_text(theme)
        current_panel_theme = get_bind_var("panel_theme")
        try:
            self.panel_theme_combo.set_active(panel_themes.index(current_panel_theme))
        except ValueError:
            self.panel_theme_combo.set_active(0)
        panel_theme_combo_container.add(self.panel_theme_combo)
        layout_grid.attach(panel_theme_combo_container, 1, 7, 1, 1)
        self.panel_theme_combo.connect(
            "changed", self._on_panel_theme_changed_for_position_sensitivity
        )

        self.panel_position_options = ["Start", "Center", "End"]

        panel_position_label = Label(
            label="Panel Position", h_align="start", v_align="center"
        )
        layout_grid.attach(panel_position_label, 2, 7, 1, 1)

        panel_position_combo_container = Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.panel_position_combo = Gtk.ComboBoxText()
        self.panel_position_combo.set_tooltip_text(
            "Select the position for the 'Panel' theme panels"
        )
        for option in self.panel_position_options:
            self.panel_position_combo.append_text(option)

        current_panel_position = get_bind_var("panel_position")
        try:
            self.panel_position_combo.set_active(
                self.panel_position_options.index(current_panel_position)
            )
        except ValueError:
            try:
                self.panel_position_combo.set_active(
                    self.panel_position_options.index("Center")
                )
            except ValueError:
                self.panel_position_combo.set_active(0)

        panel_position_combo_container.add(self.panel_position_combo)
        layout_grid.attach(panel_position_combo_container, 3, 7, 1, 1)

        notification_pos_label = Label(
            label="Notification Position", h_align="start", v_align="center"
        )
        layout_grid.attach(notification_pos_label, 0, 8, 1, 1)

        notification_pos_combo_container = Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )

        self.notification_pos_combo = Gtk.ComboBoxText()
        self.notification_pos_combo.set_tooltip_text(
            "Select where notifications appear on the screen."
        )

        notification_positions_list = ["Top", "Bottom"]
        for pos in notification_positions_list:
            self.notification_pos_combo.append_text(pos)

        current_notif_pos = get_bind_var("notif_pos")
        try:
            self.notification_pos_combo.set_active(
                notification_positions_list.index(current_notif_pos)
            )
        except ValueError:
            self.notification_pos_combo.set_active(0)

        self.notification_pos_combo.connect(
            "changed", self.on_notification_position_changed
        )

        notification_pos_combo_container.add(self.notification_pos_combo)
        layout_grid.attach(notification_pos_combo_container, 1, 8, 3, 1)

        separator2 = Box(
            style="min-height: 1px; background-color: alpha(@fg_color, 0.2); margin: 5px 0px;",
            h_expand=True,
        )
        vbox.add(separator2)

        components_header = Label(markup="<b>Modules</b>", h_align="start")
        vbox.add(components_header)
        components_grid = Gtk.Grid()
        components_grid.set_column_spacing(15)
        components_grid.set_row_spacing(8)
        components_grid.set_margin_start(10)
        components_grid.set_margin_top(5)
        vbox.add(components_grid)

        self.component_switches = {}
        component_display_names = {
            "button_apps": "App Launcher Button",
            "systray": "System Tray",
            "control": "Control Panel",
            "network": "Network Applet",
            "button_tools": "Toolbox Button",
            "sysprofiles": "Powerprofiles Switcher",
            "button_overview": "Overview Button",
            "ws_container": "Workspaces",
            "weather": "Weather Widget",
            "battery": "Battery Indicator",
            "metrics": "System Metrics",
            "language": "Language Indicator",
            "date_time": "Date & Time",
            "button_power": "Power Button",
        }

        self.corners_switch = Gtk.Switch(active=get_bind_var("corners_visible"))
        num_components = len(component_display_names) + 1
        rows_per_column = (num_components + 1) // 2

        corners_label = Label(
            label="Rounded Corners", h_align="start", v_align="center"
        )
        components_grid.attach(corners_label, 0, 0, 1, 1)
        switch_container_corners = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        switch_container_corners.add(self.corners_switch)
        components_grid.attach(switch_container_corners, 1, 0, 1, 1)

        current_row = 0
        current_col = 0
        item_idx = 0
        for i, (name, display) in enumerate(component_display_names.items()):
            if item_idx < (rows_per_column - 1):
                row = item_idx + 1
                col = 0
            else:
                row = item_idx - (rows_per_column - 1)
                col = 2

            component_label = Label(label=display, h_align="start", v_align="center")
            components_grid.attach(component_label, col, row, 1, 1)

            switch_container = Gtk.Box(
                orientation=Gtk.Orientation.HORIZONTAL,
                halign=Gtk.Align.START,
                valign=Gtk.Align.CENTER,
            )
            component_switch = Gtk.Switch(active=get_bind_var(f"bar_{name}_visible"))
            switch_container.add(component_switch)
            components_grid.attach(switch_container, col + 1, row, 1, 1)
            self.component_switches[name] = component_switch
            item_idx += 1

        self._update_panel_position_sensitivity()
        return scrolled_window

    def _on_panel_theme_changed_for_position_sensitivity(self, combo):
        self._update_panel_position_sensitivity()

    def _update_panel_position_sensitivity(self):
        if hasattr(self, "panel_theme_combo") and hasattr(self, "panel_position_combo"):
            selected_theme = self.panel_theme_combo.get_active_text()
            is_panel_theme_selected = selected_theme == "Panel"
            self.panel_position_combo.set_sensitive(is_panel_theme_selected)

    def on_notification_position_changed(self, combo: Gtk.ComboBoxText):
        selected_text = combo.get_active_text()
        if selected_text:
            bind_vars["notif_pos"] = selected_text
            print(
                f"Notification position updated in bind_vars: {bind_vars["notif_pos"]}"
            )

    def create_system_tab(self):
        scrolled_window = ScrolledWindow(
            h_scrollbar_policy="never",
            v_scrollbar_policy="automatic",
            h_expand=True,
            v_expand=True,
            propagate_width=False,
            propagate_height=False,
        )

        vbox = Box(orientation="v", spacing=15, style="margin: 15px;")
        scrolled_window.add(vbox)

        system_grid = Gtk.Grid()
        system_grid.set_column_spacing(20)
        system_grid.set_row_spacing(10)
        system_grid.set_margin_bottom(15)
        vbox.add(system_grid)

        # Auto-append checkbox - first option
        auto_append_label = Label(
            label="Auto-append to hyprland.conf", h_align="start", v_align="center"
        )
        system_grid.attach(auto_append_label, 0, 0, 1, 1)
        auto_append_switch_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        self.auto_append_switch = Gtk.Switch(
            active=get_bind_var("auto_append_hyprland"),
            tooltip_text="Automatically append Ax-Shell source string to hyprland.conf",
        )
        auto_append_switch_container.add(self.auto_append_switch)
        system_grid.attach(auto_append_switch_container, 1, 0, 1, 1)

        # Monitor Selection - second option
        monitor_header = Label(markup="<b>Monitor Selection</b>", h_align="start")
        system_grid.attach(monitor_header, 0, 1, 2, 1)

        monitor_label = Label(
            label="Show Ax-Shell on monitors:", h_align="start", v_align="center"
        )
        system_grid.attach(monitor_label, 0, 2, 1, 1)

        # Create monitor selection container
        self.monitor_selection_container = Box(
            orientation="v", spacing=5, h_align="start"
        )
        self.monitor_checkboxes = {}

        # Get available monitors
        try:
            from utils.monitor_manager import get_monitor_manager

            monitor_manager = get_monitor_manager()
            available_monitors = monitor_manager.get_monitors()
        except (ImportError, Exception) as e:
            print(f"Could not get monitor info for settings: {e}")
            available_monitors = [{"id": 0, "name": "default"}]

        # Get current selection from config
        current_selection = get_bind_var("selected_monitors")

        # Create checkboxes for each monitor
        for monitor in available_monitors:
            monitor_name = monitor.get("name", f'monitor-{monitor.get("id", 0)}')

            checkbox_container = Box(orientation="h", spacing=5, h_align="start")
            checkbox = Gtk.CheckButton(label=monitor_name)

            # Check if this monitor is selected (empty selection means all selected)
            is_selected = (
                len(current_selection) == 0 or monitor_name in current_selection
            )
            checkbox.set_active(is_selected)

            checkbox_container.add(checkbox)
            self.monitor_selection_container.add(checkbox_container)
            self.monitor_checkboxes[monitor_name] = checkbox

        # Add hint label
        hint_label = Label(
            markup="<small>Leave all unchecked to show on all monitors</small>",
            h_align="start",
        )
        self.monitor_selection_container.add(hint_label)

        system_grid.attach(self.monitor_selection_container, 1, 2, 1, 1)

        terminal_header = Label(markup="<b>Terminal Settings</b>", h_align="start")
        system_grid.attach(terminal_header, 0, 3, 2, 1)
        terminal_label = Label(label="Command:", h_align="start", v_align="center")
        system_grid.attach(terminal_label, 0, 4, 1, 1)
        self.terminal_entry = Entry(
            text=get_bind_var("terminal_command"),
            tooltip_text="Command used to launch terminal apps (e.g., 'kitty -e')",
            h_expand=True,
        )
        system_grid.attach(self.terminal_entry, 1, 4, 1, 1)
        hint_label = Label(
            markup="<small>Examples: 'kitty -e', 'alacritty -e', 'foot -e'</small>",
            h_align="start",
        )
        system_grid.attach(hint_label, 0, 5, 2, 1)

        hypr_header = Label(markup="<b>Hyprland Integration</b>", h_align="start")
        system_grid.attach(hypr_header, 2, 3, 2, 1)
        row = 4
        self.lock_switch = None
        if self.show_lock_checkbox:
            lock_label = Label(
                label="Replace Hyprlock config", h_align="start", v_align="center"
            )
            system_grid.attach(lock_label, 2, row, 1, 1)
            lock_switch_container = Gtk.Box(
                orientation=Gtk.Orientation.HORIZONTAL,
                halign=Gtk.Align.START,
                valign=Gtk.Align.CENTER,
            )
            self.lock_switch = Gtk.Switch(
                tooltip_text="Replace Hyprlock configuration with Ax-Shell's custom config"
            )
            lock_switch_container.add(self.lock_switch)
            system_grid.attach(lock_switch_container, 3, row, 1, 1)
            row += 1
        self.idle_switch = None
        if self.show_idle_checkbox:
            idle_label = Label(
                label="Replace Hypridle config", h_align="start", v_align="center"
            )
            system_grid.attach(idle_label, 2, row, 1, 1)
            idle_switch_container = Gtk.Box(
                orientation=Gtk.Orientation.HORIZONTAL,
                halign=Gtk.Align.START,
                valign=Gtk.Align.CENTER,
            )
            self.idle_switch = Gtk.Switch(
                tooltip_text="Replace Hypridle configuration with Ax-Shell's custom config"
            )
            idle_switch_container.add(self.idle_switch)
            system_grid.attach(idle_switch_container, 3, row, 1, 1)
            row += 1
        if self.show_lock_checkbox or self.show_idle_checkbox:
            note_label = Label(
                markup="<small>Existing configs will be backed up</small>",
                h_align="start",
            )
            system_grid.attach(note_label, 2, row, 2, 1)

        # Notifications app lists section
        notifications_header = Label(
            markup="<b>Notification Settings</b>", h_align="start"
        )
        vbox.add(notifications_header)

        notif_grid = Gtk.Grid()
        notif_grid.set_column_spacing(20)
        notif_grid.set_row_spacing(10)
        notif_grid.set_margin_start(10)
        notif_grid.set_margin_top(5)
        notif_grid.set_margin_bottom(15)
        vbox.add(notif_grid)

        # Limited Apps History
        limited_apps_label = Label(
            label="Limited Apps History:", h_align="start", v_align="center"
        )
        notif_grid.attach(limited_apps_label, 0, 0, 1, 1)

        limited_apps_list = get_bind_var("limited_apps_history")
        limited_apps_text = ", ".join(f'"{app}"' for app in limited_apps_list)
        self.limited_apps_entry = Entry(
            text=limited_apps_text,
            tooltip_text='Enter app names separated by commas, e.g: "Spotify", "Discord"',
            h_expand=True,
        )
        notif_grid.attach(self.limited_apps_entry, 1, 0, 1, 1)

        limited_apps_hint = Label(
            markup='<small>Apps with limited notification history (format: "App1", "App2")</small>',
            h_align="start",
        )
        notif_grid.attach(limited_apps_hint, 0, 1, 2, 1)

        # History Ignored Apps
        ignored_apps_label = Label(
            label="History Ignored Apps:", h_align="start", v_align="center"
        )
        notif_grid.attach(ignored_apps_label, 0, 2, 1, 1)

        ignored_apps_list = get_bind_var("history_ignored_apps")
        ignored_apps_text = ", ".join(f'"{app}"' for app in ignored_apps_list)
        self.ignored_apps_entry = Entry(
            text=ignored_apps_text,
            tooltip_text='Enter app names separated by commas, e.g: "Hyprshot", "Screenshot"',
            h_expand=True,
        )
        notif_grid.attach(self.ignored_apps_entry, 1, 2, 1, 1)

        ignored_apps_hint = Label(
            markup='<small>Apps whose notifications are ignored in history (format: "App1", "App2")</small>',
            h_align="start",
        )
        notif_grid.attach(ignored_apps_hint, 0, 3, 2, 1)

        metrics_header = Label(markup="<b>System Metrics Options</b>", h_align="start")
        vbox.add(metrics_header)
        metrics_grid = Gtk.Grid(
            column_spacing=15, row_spacing=8, margin_start=10, margin_top=5
        )
        vbox.add(metrics_grid)

        self.metrics_switches = {}
        self.metrics_small_switches = {}
        metric_names = {"cpu": "CPU", "ram": "RAM", "disk": "Disk", "gpu": "GPU"}

        metrics_grid.attach(Label(label="Show in Metrics", h_align="start"), 0, 0, 1, 1)
        for i, (key, label_text) in enumerate(metric_names.items()):
            switch = Gtk.Switch(active=get_bind_var("metrics_visible").get(key, True))
            self.metrics_switches[key] = switch
            metrics_grid.attach(
                Label(label=label_text, h_align="start"), 0, i + 1, 1, 1
            )
            metrics_grid.attach(switch, 1, i + 1, 1, 1)

        metrics_grid.attach(
            Label(label="Show in Small Metrics", h_align="start"), 2, 0, 1, 1
        )
        for i, (key, label_text) in enumerate(metric_names.items()):
            switch = Gtk.Switch(
                active=get_bind_var("metrics_small_visible").get(key, True)
            )
            self.metrics_small_switches[key] = switch
            metrics_grid.attach(
                Label(label=label_text, h_align="start"), 2, i + 1, 1, 1
            )
            metrics_grid.attach(switch, 3, i + 1, 1, 1)

        def enforce_minimum_metrics(switch_dict):
            enabled_switches = [s for s in switch_dict.values() if s.get_active()]
            can_disable = len(enabled_switches) > 3
            for s in switch_dict.values():
                s.set_sensitive(True if can_disable or not s.get_active() else False)

        def on_metric_toggle(switch, gparam, switch_dict):
            enforce_minimum_metrics(switch_dict)

        for k_s, s_s in self.metrics_switches.items():
            s_s.connect("notify::active", on_metric_toggle, self.metrics_switches)
        for k_s, s_s in self.metrics_small_switches.items():
            s_s.connect("notify::active", on_metric_toggle, self.metrics_small_switches)
        enforce_minimum_metrics(self.metrics_switches)
        enforce_minimum_metrics(self.metrics_small_switches)

        disks_label = Label(
            label="Disk directories for Metrics", h_align="start", v_align="center"
        )
        vbox.add(disks_label)
        self.disk_entries = Box(orientation="v", spacing=8, h_align="start")

        self._create_disk_edit_entry_func = lambda path: self._add_disk_entry_widget(
            path
        )

        for p in get_bind_var("bar_metrics_disks"):
            self._create_disk_edit_entry_func(p)
        vbox.add(self.disk_entries)

        add_container = Gtk.Box(
            orientation=Gtk.Orientation.HORIZONTAL,
            halign=Gtk.Align.START,
            valign=Gtk.Align.CENTER,
        )
        add_btn = Button(
            label="Add new disk",
            on_clicked=lambda _: self._create_disk_edit_entry_func("/"),
        )
        add_container.add(add_btn)
        vbox.add(add_container)

        return scrolled_window

    def _add_disk_entry_widget(self, path):
        """Helper para añadir una fila de entrada de disco al Box disk_entries."""
        bar = Box(orientation="h", spacing=10, h_align="start")
        entry = Entry(text=path, h_expand=True)
        bar.add(entry)
        x_btn = Button(label="X")
        x_btn.connect(
            "clicked",
            lambda _, current_bar_to_remove=bar: self.disk_entries.remove(
                current_bar_to_remove
            ),
        )
        bar.add(x_btn)
        self.disk_entries.add(bar)
        self.disk_entries.show_all()

    def create_about_tab(self):
        vbox = Box(orientation="v", spacing=18, style="margin: 30px;")
        vbox.add(
            Label(
                markup=f"<b>{APP_NAME_CAP}</b>",
                h_align="start",
                style="font-size: 1.5em; margin-bottom: 8px;",
            )
        )
        vbox.add(
            Label(
                label="A hackable shell for Hyprland, powered by Fabric.",
                h_align="start",
                style="margin-bottom: 12px;",
            )
        )
        repo_box = Box(orientation="h", spacing=6, h_align="start")
        repo_label = Label(label="GitHub:", h_align="start")
        repo_link = Label(
            markup='<a href="https://github.com/Axenide/Ax-Shell">https://github.com/Axenide/Ax-Shell</a>'
        )
        repo_box.add(repo_label)
        repo_box.add(repo_link)
        vbox.add(repo_box)

        def on_kofi_clicked(_):
            import webbrowser

            webbrowser.open("https://ko-fi.com/Axenide")

        kofi_btn = Button(
            label="Support on Ko-Fi ❤️",
            on_clicked=on_kofi_clicked,
            tooltip_text="Support Axenide on Ko-Fi",
            style="margin-top: 18px; min-width: 160px;",
        )
        vbox.add(kofi_btn)
        vbox.add(Box(v_expand=True))
        return vbox

    def on_ws_num_changed(self, switch, gparam):
        is_active = switch.get_active()
        self.ws_chinese_switch.set_sensitive(is_active)
        if not is_active:
            self.ws_chinese_switch.set_active(False)

    def on_position_changed(self, combo):
        position = combo.get_active_text()
        is_vertical = position in ["Left", "Right"]
        self.centered_switch.set_sensitive(is_vertical)
        if not is_vertical:
            self.centered_switch.set_active(False)

    def on_dock_enabled_changed(self, switch, gparam):
        is_active = switch.get_active()
        self.dock_hover_switch.set_sensitive(is_active)
        if not is_active:
            self.dock_hover_switch.set_active(False)

    def on_select_face_icon(self, widget):
        dialog = Gtk.FileChooserDialog(
            title="Select Face Icon",
            transient_for=self.get_toplevel(),
            action=Gtk.FileChooserAction.OPEN,
        )
        dialog.add_buttons(
            Gtk.STOCK_CANCEL,
            Gtk.ResponseType.CANCEL,
            Gtk.STOCK_OPEN,
            Gtk.ResponseType.OK,
        )
        image_filter = Gtk.FileFilter()
        image_filter.set_name("Image files")
        for mime in ["image/png", "image/jpeg"]:
            image_filter.add_mime_type(mime)
        for pattern in ["*.png", "*.jpg", "*.jpeg"]:
            image_filter.add_pattern(pattern)
        dialog.add_filter(image_filter)
        if dialog.run() == Gtk.ResponseType.OK:
            self.selected_face_icon = dialog.get_filename()
            self.face_status_label.label = (
                f"Selected: {os.path.basename(self.selected_face_icon)}"
            )
            try:
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                    self.selected_face_icon, 64, 64
                )
                self.face_image.set_from_pixbuf(pixbuf)
            except Exception as e:
                print(f"Error loading selected face icon preview: {e}")
                self.face_image.set_from_icon_name("image-missing", Gtk.IconSize.DIALOG)
        dialog.destroy()

    def on_accept(self, widget):
        current_bind_vars_snapshot = {}
        for prefix_key, suffix_key, prefix_entry, suffix_entry in self.entries:
            current_bind_vars_snapshot[prefix_key] = prefix_entry.get_text()
            current_bind_vars_snapshot[suffix_key] = suffix_entry.get_text()

        current_bind_vars_snapshot["wallpapers_dir"] = (
            self.wall_dir_chooser.get_filename()
        )

        current_bind_vars_snapshot["bar_position"] = (
            self.position_combo.get_active_text()
        )
        current_bind_vars_snapshot["vertical"] = current_bind_vars_snapshot[
            "bar_position"
        ] in ["Left", "Right"]

        current_bind_vars_snapshot["centered_bar"] = self.centered_switch.get_active()
        current_bind_vars_snapshot["datetime_12h_format"] = (
            self.datetime_12h_switch.get_active()
        )
        current_bind_vars_snapshot["dock_enabled"] = self.dock_switch.get_active()
        current_bind_vars_snapshot["dock_always_show"] = (
            self.dock_hover_switch.get_active()
        )
        current_bind_vars_snapshot["dock_icon_size"] = int(self.dock_size_scale.value)
        current_bind_vars_snapshot["terminal_command"] = self.terminal_entry.get_text()
        current_bind_vars_snapshot["auto_append_hyprland"] = (
            self.auto_append_switch.get_active()
        )
        current_bind_vars_snapshot["corners_visible"] = self.corners_switch.get_active()
        current_bind_vars_snapshot["bar_workspace_show_number"] = (
            self.ws_num_switch.get_active()
        )
        current_bind_vars_snapshot["bar_workspace_use_chinese_numerals"] = (
            self.ws_chinese_switch.get_active()
        )
        current_bind_vars_snapshot["bar_hide_special_workspace"] = (
            self.special_ws_switch.get_active()
        )
        current_bind_vars_snapshot["bar_theme"] = self.bar_theme_combo.get_active_text()
        current_bind_vars_snapshot["dock_theme"] = (
            self.dock_theme_combo.get_active_text()
        )
        current_bind_vars_snapshot["panel_theme"] = (
            self.panel_theme_combo.get_active_text()
        )
        current_bind_vars_snapshot["panel_position"] = (
            self.panel_position_combo.get_active_text()
        )
        selected_notif_pos_text = self.notification_pos_combo.get_active_text()
        if selected_notif_pos_text:
            current_bind_vars_snapshot["notif_pos"] = selected_notif_pos_text
        else:
            current_bind_vars_snapshot["notif_pos"] = "Top"

        for component_name, switch in self.component_switches.items():
            current_bind_vars_snapshot[f"bar_{component_name}_visible"] = (
                switch.get_active()
            )

        current_bind_vars_snapshot["metrics_visible"] = {
            k: s.get_active() for k, s in self.metrics_switches.items()
        }
        current_bind_vars_snapshot["metrics_small_visible"] = {
            k: s.get_active() for k, s in self.metrics_small_switches.items()
        }
        current_bind_vars_snapshot["bar_metrics_disks"] = [
            child.get_children()[0].get_text()
            for child in self.disk_entries.get_children()
            if isinstance(child, Gtk.Box)
            and child.get_children()
            and isinstance(child.get_children()[0], Entry)
        ]

        # Parse notification app lists
        def parse_app_list(text):
            """Parse comma-separated app names with quotes"""
            if not text.strip():
                return []
            apps = []
            for app in text.split(","):
                app = app.strip()
                if app.startswith('"') and app.endswith('"'):
                    app = app[1:-1]
                elif app.startswith("'") and app.endswith("'"):
                    app = app[1:-1]
                if app:
                    apps.append(app)
            return apps

        current_bind_vars_snapshot["limited_apps_history"] = parse_app_list(
            self.limited_apps_entry.get_text()
        )
        current_bind_vars_snapshot["history_ignored_apps"] = parse_app_list(
            self.ignored_apps_entry.get_text()
        )

        # Save monitor selection
        selected_monitors = []
        any_checked = False
        for monitor_name, checkbox in self.monitor_checkboxes.items():
            if checkbox.get_active():
                selected_monitors.append(monitor_name)
                any_checked = True

        # If no monitors are checked, use empty array (means show on all monitors)
        current_bind_vars_snapshot["selected_monitors"] = (
            selected_monitors if any_checked else []
        )

        selected_icon_path = self.selected_face_icon
        replace_lock = self.lock_switch and self.lock_switch.get_active()
        replace_idle = self.idle_switch and self.idle_switch.get_active()

        if self.selected_face_icon:
            self.selected_face_icon = None
            self.face_status_label.label = ""

        def _apply_and_reload_task_thread(user_data):
            nonlocal current_bind_vars_snapshot

            from . import settings_utils

            settings_utils.bind_vars.clear()
            settings_utils.bind_vars.update(current_bind_vars_snapshot)

            start_time = time.time()
            print(f"{start_time:.4f}: Background task started.")

            config_json = os.path.expanduser(
                f"~/.config/{APP_NAME_CAP}/config/config.json"
            )
            os.makedirs(os.path.dirname(config_json), exist_ok=True)
            try:
                with open(config_json, "w") as f:
                    json.dump(settings_utils.bind_vars, f, indent=4)
                print(f"{time.time():.4f}: Saved config.json.")
            except Exception as e:
                print(f"Error saving config.json: {e}")

            if selected_icon_path:
                print(f"{time.time():.4f}: Processing face icon...")
                try:
                    img = Image.open(selected_icon_path)
                    side = min(img.size)
                    left = (img.width - side) // 2
                    top = (img.height - side) // 2
                    cropped_img = img.crop((left, top, left + side, top + side))
                    face_icon_dest = os.path.expanduser("~/.face.icon")
                    cropped_img.save(face_icon_dest, format="PNG")
                    print(f"{time.time():.4f}: Face icon saved to {face_icon_dest}")
                    GLib.idle_add(self._update_face_image_widget, face_icon_dest)
                except Exception as e:
                    print(f"Error processing face icon: {e}")
                print(f"{time.time():.4f}: Finished processing face icon.")

            if replace_lock:
                print(f"{time.time():.4f}: Replacing hyprlock config...")
                src = os.path.expanduser(
                    f"~/.config/{APP_NAME_CAP}/config/hypr/hyprlock.conf"
                )
                dest = os.path.expanduser("~/.config/hypr/hyprlock.conf")
                if os.path.exists(src):
                    backup_and_replace(src, dest, "Hyprlock")
                else:
                    print(f"Warning: Source hyprlock config not found at {src}")
                print(f"{time.time():.4f}: Finished replacing hyprlock config.")

            if replace_idle:
                print(f"{time.time():.4f}: Replacing hypridle config...")
                src = os.path.expanduser(
                    f"~/.config/{APP_NAME_CAP}/config/hypr/hypridle.conf"
                )
                dest = os.path.expanduser("~/.config/hypr/hypridle.conf")
                if os.path.exists(src):
                    backup_and_replace(src, dest, "Hypridle")
                else:
                    print(f"Warning: Source hypridle config not found at {src}")
                print(f"{time.time():.4f}: Finished replacing hypridle config.")

            print(
                f"{time.time():.4f}: Checking/Appending hyprland.conf source string..."
            )
            hypr_path = os.path.expanduser("~/.config/hypr/hyprland.conf")
            try:
                from .settings_constants import SOURCE_STRING

                # Check if auto-append is enabled
                auto_append_enabled = current_bind_vars_snapshot.get(
                    "auto_append_hyprland", True
                )
                if auto_append_enabled:
                    needs_append = True
                    if os.path.exists(hypr_path):
                        with open(hypr_path, "r") as f:
                            if SOURCE_STRING.strip() in f.read():
                                needs_append = False
                    else:
                        os.makedirs(os.path.dirname(hypr_path), exist_ok=True)

                    if needs_append:
                        with open(hypr_path, "a") as f:
                            f.write("\n" + SOURCE_STRING)
                        print(f"Appended source string to {hypr_path}")
                    else:
                        print("Source string already present in hyprland.conf")
                else:
                    print("Auto-append to hyprland.conf is disabled")
            except Exception as e:
                print(f"Error updating {hypr_path}: {e}")
            print(
                f"{time.time():.4f}: Finished checking/appending hyprland.conf source string."
            )

            print(f"{time.time():.4f}: Running start_config()...")
            start_config()
            print(f"{time.time():.4f}: Finished start_config().")

            print(f"{time.time():.4f}: Initiating Ax-Shell restart using Popen...")
            main_py = os.path.expanduser(f"~/.config/{APP_NAME_CAP}/main.py")
            kill_cmd = f"killall {APP_NAME}"
            start_cmd = ["uwsm", "app", "--", "python", main_py]
            try:
                kill_proc = subprocess.Popen(
                    kill_cmd,
                    shell=True,
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                kill_proc.wait(timeout=2)
                print(f"{time.time():.4f}: killall process finished (o timed out).")
            except subprocess.TimeoutExpired:
                print("Warning: killall command timed out.")
            except Exception as e:
                print(f"Error running killall: {e}")

            try:
                subprocess.Popen(
                    start_cmd,
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                    start_new_session=True,
                )
                print(f"{APP_NAME_CAP} restart initiated via Popen.")
            except FileNotFoundError as e:
                print(f"Error restarting {APP_NAME_CAP}: Command not found ({e})")
            except Exception as e:
                print(f"Error restarting {APP_NAME_CAP} via Popen: {e}")

            print(f"{time.time():.4f}: Ax-Shell restart commands issued via Popen.")
            end_time = time.time()
            print(
                f"{end_time:.4f}: Background task finished (Total: {end_time - start_time:.4f}s)."
            )

        GLib.Thread.new("apply-reload-task", _apply_and_reload_task_thread, None)
        print("Configuration apply/reload task started in background.")

    def _update_face_image_widget(self, icon_path):
        try:
            if self.face_image and self.face_image.get_window():
                pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_path, 64, 64)
                self.face_image.set_from_pixbuf(pixbuf)
        except Exception as e:
            print(f"Error reloading face icon preview: {e}")
            if self.face_image and self.face_image.get_window():
                self.face_image.set_from_icon_name("image-missing", Gtk.IconSize.DIALOG)
        return GLib.SOURCE_REMOVE

    def on_reset(self, widget):
        dialog = Gtk.MessageDialog(
            transient_for=self.get_toplevel(),
            flags=0,
            message_type=Gtk.MessageType.QUESTION,
            buttons=Gtk.ButtonsType.YES_NO,
            text="Reset all settings to defaults?",
        )
        dialog.format_secondary_text(
            "This will reset all keybindings and appearance settings to their default values."
        )
        if dialog.run() == Gtk.ResponseType.YES:
            from . import settings_utils
            from .settings_constants import DEFAULTS

            settings_utils.bind_vars.clear()
            settings_utils.bind_vars.update(DEFAULTS.copy())

            for prefix_key, suffix_key, prefix_entry, suffix_entry in self.entries:
                prefix_entry.set_text(settings_utils.bind_vars[prefix_key])
                suffix_entry.set_text(settings_utils.bind_vars[suffix_key])

            self.wall_dir_chooser.set_filename(
                settings_utils.bind_vars["wallpapers_dir"]
            )

            positions = ["Top", "Bottom", "Left", "Right"]
            default_position = get_default("bar_position")
            try:
                self.position_combo.set_active(positions.index(default_position))
            except ValueError:
                self.position_combo.set_active(0)

            self.centered_switch.set_active(get_bind_var("centered_bar"))
            self.centered_switch.set_sensitive(default_position in ["Left", "Right"])

            self.datetime_12h_switch.set_active(get_bind_var("datetime_12h_format"))

            self.dock_switch.set_active(get_bind_var("dock_enabled"))
            self.dock_hover_switch.set_active(get_bind_var("dock_always_show"))
            self.dock_hover_switch.set_sensitive(self.dock_switch.get_active())
            self.dock_size_scale.set_value(get_bind_var("dock_icon_size"))
            self.terminal_entry.set_text(settings_utils.bind_vars["terminal_command"])
            self.auto_append_switch.set_active(get_bind_var("auto_append_hyprland"))
            self.ws_num_switch.set_active(get_bind_var("bar_workspace_show_number"))
            self.ws_chinese_switch.set_active(
                get_bind_var("bar_workspace_use_chinese_numerals")
            )
            self.ws_chinese_switch.set_sensitive(self.ws_num_switch.get_active())
            self.special_ws_switch.set_active(
                get_bind_var("bar_hide_special_workspace")
            )

            default_theme_val = get_default("bar_theme")
            themes = ["Pills", "Dense", "Edge"]
            try:
                self.bar_theme_combo.set_active(themes.index(default_theme_val))
            except ValueError:
                self.bar_theme_combo.set_active(0)

            default_dock_theme_val = get_default("dock_theme")
            try:
                self.dock_theme_combo.set_active(themes.index(default_dock_theme_val))
            except ValueError:
                self.dock_theme_combo.set_active(0)

            default_panel_theme_val = get_default("panel_theme")
            panel_themes_options = ["Notch", "Panel"]
            try:
                self.panel_theme_combo.set_active(
                    panel_themes_options.index(default_panel_theme_val)
                )
            except ValueError:
                self.panel_theme_combo.set_active(0)

            default_panel_position_val = get_default("panel_position")
            try:
                self.panel_position_combo.set_active(
                    self.panel_position_options.index(default_panel_position_val)
                )
            except ValueError:
                try:
                    self.panel_position_combo.set_active(
                        self.panel_position_options.index("Center")
                    )
                except ValueError:
                    self.panel_position_combo.set_active(0)

            default_notif_pos_val = get_default("notif_pos")
            notification_positions_list = ["Top", "Bottom"]
            try:
                self.notification_pos_combo.set_active(
                    notification_positions_list.index(default_notif_pos_val)
                )
            except ValueError:
                self.notification_pos_combo.set_active(0)

            for name, switch in self.component_switches.items():
                switch.set_active(get_bind_var(f"bar_{name}_visible"))
            self.corners_switch.set_active(get_bind_var("corners_visible"))

            metrics_vis_defaults = get_default("metrics_visible")
            for k, s_widget in self.metrics_switches.items():
                s_widget.set_active(metrics_vis_defaults.get(k, True))

            metrics_small_vis_defaults = get_default("metrics_small_visible")
            for k, s_widget in self.metrics_small_switches.items():
                s_widget.set_active(metrics_small_vis_defaults.get(k, True))

            def enforce_minimum_metrics(switch_dict):
                enabled_switches = [
                    s_widget
                    for s_widget in switch_dict.values()
                    if s_widget.get_active()
                ]
                can_disable = len(enabled_switches) > 3
                for s_widget in switch_dict.values():
                    s_widget.set_sensitive(
                        True if can_disable or not s_widget.get_active() else False
                    )

            enforce_minimum_metrics(self.metrics_switches)
            enforce_minimum_metrics(self.metrics_small_switches)

            for child in list(self.disk_entries.get_children()):
                self.disk_entries.remove(child)

            for p in get_default("bar_metrics_disks"):
                self._add_disk_edit_entry_func(p)

            # Reset notification app lists
            limited_apps_list = get_default("limited_apps_history")
            limited_apps_text = ", ".join(f'"{app}"' for app in limited_apps_list)
            self.limited_apps_entry.set_text(limited_apps_text)

            ignored_apps_list = get_default("history_ignored_apps")
            ignored_apps_text = ", ".join(f'"{app}"' for app in ignored_apps_list)
            self.ignored_apps_entry.set_text(ignored_apps_text)

            # Reset monitor selection
            default_monitors = get_default("selected_monitors")
            for monitor_name, checkbox in self.monitor_checkboxes.items():
                # If defaults is empty, check all monitors (show on all)
                is_selected = (
                    len(default_monitors) == 0 or monitor_name in default_monitors
                )
                checkbox.set_active(is_selected)

            self._update_panel_position_sensitivity()

            self.selected_face_icon = None
            self.face_status_label.label = ""
            current_face = os.path.expanduser("~/.face.icon")
            try:
                pixbuf = (
                    GdkPixbuf.Pixbuf.new_from_file_at_size(current_face, 64, 64)
                    if os.path.exists(current_face)
                    else None
                )
                if pixbuf:
                    self.face_image.set_from_pixbuf(pixbuf)
                else:
                    self.face_image.set_from_icon_name("user-info", Gtk.IconSize.DIALOG)
            except Exception:
                self.face_image.set_from_icon_name("image-missing", Gtk.IconSize.DIALOG)

            if self.lock_switch:
                self.lock_switch.set_active(False)
            if self.idle_switch:
                self.idle_switch.set_active(False)
            print("Settings reset to defaults.")
        dialog.destroy()

    def on_close(self, widget):
        if self.application:
            self.application.quit()
        else:
            self.destroy()
