import os
import sys
import time
import subprocess
import ctypes
from ctypes import wintypes

PROCESS_TERMINATE = 0x0001
PROCESS_QUERY_INFORMATION = 0x0400

kernel32 = ctypes.windll.kernel32
kernel32.OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
kernel32.OpenProcess.restype = wintypes.HANDLE
kernel32.TerminateProcess.argtypes = [wintypes.HANDLE, wintypes.UINT]
kernel32.TerminateProcess.restype = wintypes.BOOL
kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
kernel32.CloseHandle.restype = wintypes.BOOL
kernel32.GetLastError.argtypes = []
kernel32.GetLastError.restype = wintypes.DWORD


def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except Exception:
        return False


def elevate():
    if is_admin():
        return
    script = ' '.join(sys.argv)
    ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, script, None, 1
    )
    sys.exit(0)


def get_processes():
    """Return list of (pid, ppid, name) via wmic."""
    try:
        proc = subprocess.run(
            ["wmic", "process", "get", "ProcessId,ParentProcessId,Name",
             "/FORMAT:CSV"],
            capture_output=True, text=True, creationflags=subprocess.CREATE_NO_WINDOW
        )
    except FileNotFoundError:
        # fallback: PowerShell
        proc = subprocess.run(
            ["powershell", "-Command",
             "Get-CimInstance Win32_Process | ForEach-Object { "
             "$_.ProcessId.ToString() + ',' + $_.ParentProcessId.ToString() + ',' + $_.Name }"],
            capture_output=True, text=True, creationflags=subprocess.CREATE_NO_WINDOW
        )
        result = []
        for line in proc.stdout.strip().split('\n'):
            line = line.strip()
            if not line:
                continue
            parts = line.split(',', 2)
            if len(parts) == 3:
                pid, ppid, name = parts
                try:
                    result.append((int(pid), int(ppid), name))
                except ValueError:
                    pass
        return result

    result = []
    for line in proc.stdout.strip().split('\n')[1:]:  # skip CSV header
        line = line.strip()
        if not line:
            continue
        parts = line.split(',')
        if len(parts) >= 4:
            name = parts[1].strip()
            try:
                ppid = int(parts[2].strip())
                pid = int(parts[3].strip())
            except ValueError:
                continue
            result.append((pid, ppid, name))
    return result


def kill_tree(pid, processes):
    """Recursively terminate pid and all its children via OpenProcess + TerminateProcess."""
    for p, pp, _ in processes:
        if pp == pid:
            kill_tree(p, processes)

    h_process = kernel32.OpenProcess(PROCESS_TERMINATE, False, pid)
    if h_process:
        if kernel32.TerminateProcess(h_process, 0):
            print(f"Killed: PID {pid}")
        else:
            err = kernel32.GetLastError()
            print(f"Failed to kill PID {pid}, error: {err}")
        kernel32.CloseHandle(h_process)
    else:
        print(f"Failed to kill PID {pid}, error: {kernel32.GetLastError()}")


def clear_hosts():
    path = r"C:\Windows\System32\drivers\etc\hosts"
    try:
        with open(path, 'w') as f:
            pass
        print("Hosts file cleared.")
    except Exception as e:
        print(f"Failed to clear hosts file, error: {e}")


def main():
    elevate()

    MAX_ATTEMPTS = 5
    for attempt in range(1, MAX_ATTEMPTS + 1):
        print(f"\n=== Attempt {attempt}/{MAX_ATTEMPTS} ===")

        processes = get_processes()
        target = None
        for pid, ppid, name in processes:
            if name.lower() == "jfglzsn.exe":
                target = (pid, ppid, name)
                print(f"Found jfglzsn.exe (PID: {pid}), parent PID: {ppid}")
                kill_tree(ppid, processes)
                break

        if not target:
            print("jfglzsn.exe not found.")

        if attempt < MAX_ATTEMPTS:
            time.sleep(1)

    print("jfglzs killed! fixing network...")
    clear_hosts()
    os.system("pause")


if __name__ == "__main__":
    main()
