import os
import sys
import time
import ctypes
import subprocess
import urllib.request
import winreg

CREATE_NO_WINDOW = 0x08000000

SERVER = "116.203.52.248"
KEY = "VoNciHfK04+8tqVDJH8gLs5CbsXpECQ4jBTuFPEt1XU="
API_URL = "https://admin.compartsystems.pt/api/clients?secret=cs-remote-2026-xK9mP"

CONFIG2_TOML = f"""rendezvous_server = '{SERVER}:21116'
nat_type = 1
serial = 0
unlock_pin = ''
trusted_devices = ''

[options]
custom-rendezvous-server = '{SERVER}:21116'
relay-server = '{SERVER}:21117'
key = '{KEY}'
"""

CONFIG_TOML = """key_confirmed = true
"""

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

def run_as_admin():
    params = f'"{os.path.abspath(sys.argv[0])}"'
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, params, None, 1)

def run_hidden(cmd, **kwargs):
    if isinstance(cmd, str):
        cmd = cmd.split()
    si = subprocess.STARTUPINFO()
    si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    si.wShowWindow = 0
    return subprocess.run(cmd, startupinfo=si, creationflags=CREATE_NO_WINDOW, **kwargs)

def msg_box(text, title="CompArt Assistencia Remota"):
    ctypes.windll.user32.MessageBoxW(0, text, title, 0x40)

def find_rustdesk():
    candidates = [
        os.path.join(os.environ.get("ProgramFiles", "C:\\Program Files"), "RustDesk", "rustdesk.exe"),
        os.path.join(os.environ.get("ProgramFiles(x86)", "C:\\Program Files (x86)"), "RustDesk", "rustdesk.exe"),
        os.path.join(os.environ.get("LOCALAPPDATA", ""), "RustDesk", "rustdesk.exe"),
        os.path.join(os.environ.get("APPDATA", ""), "RustDesk", "rustdesk.exe"),
        os.path.join(os.environ.get("USERPROFILE", "C:\\Users\\user"), "Downloads", "rustdesk.exe"),
    ]
    for p in candidates:
        if os.path.exists(p):
            return p
    return None

def get_original_user_profile():
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", access=winreg.KEY_READ)
        i = 0
        while True:
            try:
                sid = winreg.EnumKey(key, i)
                if sid.startswith("S-1-5-21") and not sid.endswith("-500"):
                    prof_path = winreg.QueryValueEx(winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\{sid}"), "ProfileImagePath")[0]
                    if os.path.exists(prof_path):
                        return prof_path, sid
                i += 1
            except WindowsError:
                break
    except:
        pass
    return os.environ.get("USERPROFILE", "C:\\Users\\user"), None

def main():
    if not is_admin():
        run_as_admin()
        return

    rustdesk_exe = find_rustdesk()
    if not rustdesk_exe:
        msg_box("RustDesk nao foi encontrado neste PC.\n\nInstale o RustDesk primeiro (ou use o instalador da CompArt).")
        return

    # Kill RustDesk para poder escrever a config
    run_hidden(["taskkill", "/f", "/im", "rustdesk.exe"], capture_output=True)
    run_hidden(["taskkill", "/f", "/im", "RustDesk.exe"], capture_output=True)
    run_hidden(["net", "stop", "RustDesk"], capture_output=True)
    time.sleep(3)

    user_profile, user_sid = get_original_user_profile()
    user_appdata = os.path.join(user_profile, "AppData", "Roaming")
    user_local_appdata = os.path.join(user_profile, "AppData", "Local")

    # Limpar configs antigas (do servidor anterior do cliente)
    clean_paths = [
        os.path.join(user_appdata, "RustDesk", "config", "RustDesk2.toml"),
        os.path.join(user_appdata, "RustDesk", "RustDesk2.toml"),
        os.path.join(user_local_appdata, "RustDesk", "config", "RustDesk2.toml"),
        r"C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config\RustDesk2.toml",
        r"C:\Windows\ServiceProfiles\LocalService\AppData\Local\RustDesk\config\RustDesk2.toml",
    ]
    for f in clean_paths:
        if os.path.exists(f):
            try:
                os.chmod(f, 0o777)
            except:
                pass
            try:
                os.remove(f)
            except:
                pass

    # Escrever config CompArt
    config_dirs = [
        os.path.join(user_appdata, "RustDesk", "config"),
        os.path.join(user_local_appdata, "RustDesk", "config"),
        r"C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config",
        r"C:\Windows\ServiceProfiles\LocalService\AppData\Local\RustDesk\config",
    ]
    for d in config_dirs:
        try:
            os.makedirs(d, exist_ok=True)
            for fname, content in [("RustDesk2.toml", CONFIG2_TOML), ("RustDesk.toml", CONFIG_TOML)]:
                toml_path = os.path.join(d, fname)
                if os.path.exists(toml_path):
                    try:
                        os.chmod(toml_path, 0o777)
                    except:
                        pass
                with open(toml_path, "w", encoding="utf-8") as f:
                    f.write(content)
            try:
                os.chmod(toml_path, 0o444)
            except:
                pass
        except:
            pass

    # Registo
    for reg_root, reg_path in [(winreg.HKEY_CURRENT_USER, r"Software\RustDesk\config"), (winreg.HKEY_LOCAL_MACHINE, r"Software\RustDesk\config")]:
        try:
            key = winreg.CreateKey(reg_root, reg_path)
            winreg.SetValueEx(key, "custom-rendezvous-server", 0, winreg.REG_SZ, SERVER)
            winreg.SetValueEx(key, "relay-server", 0, winreg.REG_SZ, SERVER)
            winreg.SetValueEx(key, "key", 0, winreg.REG_SZ, KEY)
            winreg.CloseKey(key)
        except:
            pass

    # Garantir servico
    run_hidden(["sc", "config", "RustDesk", "start=auto"], capture_output=True)
    run_hidden(["net", "start", "RustDesk"], capture_output=True)

    # Arrancar UI
    subprocess.Popen([rustdesk_exe])
    time.sleep(5)

    # Obter ID
    rustdesk_id = ""
    try:
        result = run_hidden([rustdesk_exe, "--get-id"], capture_output=True, text=True, timeout=15)
        rustdesk_id = result.stdout.strip()
        if not rustdesk_id or len(rustdesk_id) < 6:
            rustdesk_id = ""
    except:
        pass

    # Registar no admin + heartbeat
    if rustdesk_id:
        try:
            hostname = os.environ.get("COMPUTERNAME", "Desconhecido")
            data = f'{{"rustdesk_id": "{rustdesk_id}", "hostname": "{hostname}"}}'.encode("utf-8")
            req = urllib.request.Request(API_URL, data=data, headers={"Content-Type": "application/json"}, method="POST")
            urllib.request.urlopen(req, timeout=10)
        except:
            pass

        try:
            heartbeat_dir = os.path.join(os.environ.get("ProgramFiles", "C:\\Program Files"), "CompArt")
            os.makedirs(heartbeat_dir, exist_ok=True)
            with open(os.path.join(heartbeat_dir, "rustdesk_id.txt"), "w", encoding="utf-8") as f:
                f.write(rustdesk_id)
            heartbeat_ps1 = os.path.join(heartbeat_dir, "heartbeat.ps1")
            with open(heartbeat_ps1, "w", encoding="utf-8") as f:
                f.write(f'''try {{
    $id = Get-Content "C:\\Program Files\\CompArt\\rustdesk_id.txt" -ErrorAction SilentlyContinue
    if ($id -match "^\\d{{6,}}$") {{
        $body = '{{"rustdesk_id": "' + $id.Trim() + '", "hostname": "' + $env:COMPUTERNAME + '"}}'
        Invoke-RestMethod -Uri "{API_URL}" -Method Post -Body $body -ContentType "application/json" -TimeoutSec 10 | Out-Null
    }}
}} catch {{}}''')
            heartbeat_vbs = os.path.join(heartbeat_dir, "heartbeat.vbs")
            with open(heartbeat_vbs, "w", encoding="utf-8") as f:
                f.write(f'CreateObject("WScript.Shell").Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -File \\"{heartbeat_ps1}\\"", 0, False')
            task_name = "CompArt-Heartbeat"
            run_hidden(["schtasks", "/delete", "/tn", task_name, "/f"], capture_output=True)
            run_hidden(["schtasks", "/create", "/tn", task_name, "/tr", f'wscript.exe "{heartbeat_vbs}"', "/sc", "minute", "/mo", "5", "/ru", "SYSTEM", "/rl", "highest", "/f"], capture_output=True)
        except:
            pass

    if rustdesk_id:
        msg_box(f"RustDesk configurado com o servidor CompArt!\n\nID: {rustdesk_id}\n\nPartilhe este ID com o tecnico.\nTelefone: 933 946 917")
    else:
        msg_box("RustDesk configurado. Nao foi possivel ler o ID automaticamente.\n\nAbra o RustDesk e leia o ID no ecra.")

if __name__ == "__main__":
    main()
