"""Layar kunci layar-penuh. Hanya bisa dibuka dari Central.

Saat terkunci:
  - jendela hitam menutup SEMUA monitor, selalu di paling atas, merebut fokus
  - semua tombol keyboard ditelan (hook level rendah, Windows)
  - Task Manager dimatikan lewat kebijakan registry sementara
Ctrl+Alt+Del tidak bisa diblokir aplikasi biasa; tetapi tanpa Task Manager, agent
tetap jalan dan layar kunci muncul lagi setelah sign-out / restart.
"""
import sys

IS_WIN = sys.platform == "win32"

if IS_WIN:
    import ctypes
    from ctypes import wintypes
    import winreg

    user32 = ctypes.windll.user32
    kernel32 = ctypes.windll.kernel32

    WH_KEYBOARD_LL = 13
    LRESULT = ctypes.c_ssize_t
    HOOKPROC = ctypes.WINFUNCTYPE(LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
    user32.SetWindowsHookExW.argtypes = [ctypes.c_int, HOOKPROC, wintypes.HINSTANCE, wintypes.DWORD]
    user32.SetWindowsHookExW.restype = wintypes.HHOOK
    user32.CallNextHookEx.argtypes = [wintypes.HHOOK, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM]
    user32.CallNextHookEx.restype = LRESULT
    user32.UnhookWindowsHookEx.argtypes = [wintypes.HHOOK]
    kernel32.GetModuleHandleW.restype = wintypes.HMODULE

    POLICY_KEY = r"Software\Microsoft\Windows\CurrentVersion\Policies\System"


def virtual_screen():
    """(x, y, lebar, tinggi) gabungan semua monitor."""
    if IS_WIN:
        return (user32.GetSystemMetrics(76), user32.GetSystemMetrics(77),
                user32.GetSystemMetrics(78), user32.GetSystemMetrics(79))
    return (0, 0, 1280, 720)


def set_taskmgr_disabled(disabled):
    if not IS_WIN:
        return
    try:
        with winreg.CreateKey(winreg.HKEY_CURRENT_USER, POLICY_KEY) as key:
            if disabled:
                winreg.SetValueEx(key, "DisableTaskMgr", 0, winreg.REG_DWORD, 1)
            else:
                try:
                    winreg.DeleteValue(key, "DisableTaskMgr")
                except FileNotFoundError:
                    pass
    except OSError:
        pass


class LockScreen:
    def __init__(self, root):
        import tkinter as tk
        self.tk = tk
        self.root = root
        self.win = None
        self.msg_var = None
        self._hook = None
        self._hook_proc = None

    @property
    def is_locked(self):
        return self.win is not None

    def set(self, locked, message=""):
        """Dipanggil berulang dari loop utama; aman dipanggil dengan nilai yang sama."""
        if locked:
            self.show(message)
        else:
            self.hide()

    # -- tampilan -----------------------------------------------------------
    def show(self, message=""):
        text = message or "Komputer ini dikunci oleh administrator."
        if self.win is not None:
            self.msg_var.set(text)
            return
        tk = self.tk
        win = tk.Toplevel(self.root)
        win.overrideredirect(True)
        win.configure(bg="#0b1220", cursor="arrow")
        x, y, w, h = virtual_screen()
        win.geometry("%dx%d+%d+%d" % (w, h, x, y))
        win.attributes("-topmost", True)
        win.protocol("WM_DELETE_WINDOW", lambda: None)
        win.bind("<Key>", lambda e: "break")
        box = tk.Frame(win, bg="#0b1220")
        box.place(relx=0.5, rely=0.5, anchor="center")
        tk.Label(box, text="\U0001F512", font=("Segoe UI Emoji", 72), bg="#0b1220", fg="#e5e7eb").pack()
        tk.Label(box, text="KOMPUTER TERKUNCI", font=("Segoe UI", 34, "bold"), bg="#0b1220", fg="#f8fafc").pack(pady=(10, 4))
        self.msg_var = tk.StringVar(value=text)
        tk.Label(box, textvariable=self.msg_var, font=("Segoe UI", 16), bg="#0b1220", fg="#94a3b8",
                 wraplength=800, justify="center").pack()
        tk.Label(box, text="Hubungi administrator untuk membuka kunci.", font=("Segoe UI", 12),
                 bg="#0b1220", fg="#64748b").pack(pady=(24, 0))
        self.win = win
        win.focus_force()
        try:
            win.grab_set()
        except Exception:
            pass
        set_taskmgr_disabled(True)
        self._install_hook()
        self._keep_front()

    def _keep_front(self):
        if self.win is None:
            return
        try:
            x, y, w, h = virtual_screen()  # monitor bisa dicolok/dicabut saat terkunci
            self.win.geometry("%dx%d+%d+%d" % (w, h, x, y))
            self.win.attributes("-topmost", True)
            self.win.lift()
            self.win.focus_force()
        except Exception:
            pass
        self.root.after(300, self._keep_front)

    def hide(self):
        if self.win is None:
            return
        self._remove_hook()
        set_taskmgr_disabled(False)
        try:
            self.win.grab_release()
        except Exception:
            pass
        self.win.destroy()
        self.win = None
        self.msg_var = None

    # -- hook keyboard (Windows) -------------------------------------------
    def _install_hook(self):
        if not IS_WIN or self._hook:
            return

        def proc(n_code, w_param, l_param):
            if n_code >= 0:
                return 1  # telan semua tombol
            return user32.CallNextHookEx(None, n_code, w_param, l_param)

        self._hook_proc = HOOKPROC(proc)  # simpan referensi agar tidak di-GC
        self._hook = user32.SetWindowsHookExW(WH_KEYBOARD_LL, self._hook_proc,
                                              kernel32.GetModuleHandleW(None), 0)

    def _remove_hook(self):
        if IS_WIN and self._hook:
            user32.UnhookWindowsHookEx(self._hook)
        self._hook = None
        self._hook_proc = None
