Загрузка данных


# Dozor/modules/administrator/admin_user_inter.py
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog

from modules.administrator.user_logic import UserLogic


class AdminUserInter(tk.Toplevel):
    def __init__(self, parent, on_logout_callback=None):
        super().__init__(parent)
        self.parent_main = parent
        self.on_logout_callback = on_logout_callback
        
        self.title("Управление пользователями")
        self.geometry("550x450") 
        self.resizable(True, True)
        self.transient(parent)
        self.grab_set()

        container = ttk.Frame(self, padding="20")
        container.pack(expand=True, fill="both")

        left_panel = ttk.Frame(container)
        left_panel.pack(side="left", fill="y", padx=(0, 10))
        right_panel = ttk.Frame(container)
        right_panel.pack(side="right", fill="both", expand=True)

        actions = [
            ("Добавить пользователя", self.action_add),
            ("Сменить пользователя", self.action_change),
            ("Удалить пользователя", self.action_remove)
        ]
        for text, cmd in actions:
            ttk.Button(left_panel, text=text, command=cmd).pack(fill="x", pady=5)

        columns = ("№", "Логин", "Роль")
        self.users_tree = ttk.Treeview(right_panel, columns=columns, show="headings")
        
        self.users_tree.heading("#1", text="№")
        self.users_tree.column("#1", anchor="center", width=50)
        
        self.users_tree.heading("#2", text="Логин")
        self.users_tree.column("#2", anchor="w", width=180)
        
        self.users_tree.heading("#3", text="Роль")
        self.users_tree.column("#3", anchor="center", width=240)
        
        self.users_tree.pack(fill="both", expand=True)

        # Хранилище реального ID для удаления
        self._currently_selected_real_id = None
        
        # Отслеживание выбора строки
        self.users_tree.bind("<<TreeviewSelect>>", self._on_tree_select)
        
        self.user_manager = UserLogic() 
        self.load_data()

        self.update_idletasks()
        p_x = self.parent_main.winfo_rootx()
        p_y = self.parent_main.winfo_rooty()
        x = p_x + 20
        y = p_y + 20
        self.geometry(f"+{x}+{y}")

    def _on_tree_select(self, event):
        selected_item = self.users_tree.selection()
        if selected_item:
            tags = self.users_tree.item(selected_item)['tags']
            if tags:
                try:
                    self._currently_selected_real_id = int(tags[0])
                except ValueError:
                    self._currently_selected_real_id = None

    def load_data(self):
        for i in self.users_tree.get_children():
            self.users_tree.delete(i)
            
        users_from_db = self.user_manager.get_all_users()
        
        for idx, user_row in enumerate(users_from_db, start=1):
            login = user_row[1]
            role = user_row[2]
            real_id = user_row[0]
            self.users_tree.insert("", "end", values=(idx, login, role), tags=(str(real_id),))

    def action_add(self):
        dialog = tk.Toplevel(self)
        dialog.title("Новый пользователь")
        dialog.geometry("300x220")
        dialog.transient(self)
        dialog.grab_set()
        
        main_frame = ttk.Frame(dialog, padding="15")
        main_frame.pack(expand=True, fill="both")

        ttk.Label(main_frame, text="Логин:").grid(row=0, column=0, sticky="w", pady=5)
        login_e = ttk.Entry(main_frame); login_e.grid(row=0, column=1, padx=5, pady=5, sticky="ew")
        
        ttk.Label(main_frame, text="Пароль:").grid(row=1, column=0, sticky="w", pady=5)
        pass_e = ttk.Entry(main_frame, show="*"); pass_e.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
        
        ttk.Label(main_frame, text="Роль:").grid(row=2, column=0, sticky="w", pady=5)
        role_values = ["Администратор", "Эксперт", "Пользователь"]
        role_combo = ttk.Combobox(main_frame, values=role_values, state="readonly")
        role_combo.current(2) 
        role_combo.grid(row=2, column=1, padx=5, pady=5, sticky="ew")

        btn_frame = ttk.Frame(main_frame)
        btn_frame.grid(row=3, column=0, columnspan=2, pady=15)

        def do_add():
            try:
                self.user_manager.add_user(login_e.get(), role_combo.get(), pass_e.get())
                self.load_data()
                dialog.destroy()
                messagebox.showinfo("Успех", "Пользователь добавлен.")
            except Exception as e:
                messagebox.showerror("Ошибка", str(e))

        ttk.Button(btn_frame, text="Создать", command=do_add).pack(side="left", padx=5)
        main_frame.columnconfigure(1, weight=1)
        login_e.focus()
        
    def action_remove(self):
        if self._currently_selected_real_id is None:
            messagebox.showwarning("Ошибка", "Выберите пользователя для удаления!")
            return
        
        answer = messagebox.askyesno(
            "Подтверждение", 
            f"УДАЛИТЬ пользователя с реальным ID={self._currently_selected_real_id}?\nЭто действие нельзя отменить."
        )
        if answer:
            try:
                self.user_manager.delete_user(self._currently_selected_real_id)
                self._currently_selected_real_id = None
                self.load_data()
                messagebox.showinfo("Успех", "Пользователь удален.")
            except Exception as e:
                messagebox.showerror("Ошибка", str(e))

    # === ИСПРАВЛЕННЫЙ МЕТОД СМЕНЫ ПОЛЬЗОВАТЕЛЯ ===
    def action_change(self):
        # 1. Сначала получаем ссылку на ГЛАВНОЕ ОКНО (оно еще живо)
        root = self.parent_main.winfo_toplevel()
        
        # 2. Останавливаем работу главного окна (его внутренний цикл Tcl)
        try:
            if hasattr(root, 'quit'):
                root.quit()
        except Exception:
            pass

        # 3. Закрываем само окно админки
        self.destroy()

        # 4. Теперь пытаемся уничтожить нативное окно ОС
        try:
            if root and root.winfo_exists():
                root.destroy()
        except Exception:
            pass

        # 5. Запускаем новый процесс
        import sys, subprocess, os, shutil
        
        script_path = os.path.abspath("main.py")
        gui_python = shutil.which("pythonw.exe") 

        if not gui_python:
            current_dir = os.path.dirname(sys.executable)
            potential_path = os.path.join(current_dir, "pythonw.exe")
            gui_python = potential_path if os.path.exists(potential_path) else sys.executable

        try:
            subprocess.Popen([gui_python, script_path], shell=True, creationflags=subprocess.CREATE_NO_WINDOW if os.name == 'nt' else 0)
        except Exception as e:
            print(f"[FATAL] Не удалось запустить новую копию Dozor: {e}")

        sys.exit(0)