import os
import sys
import time
import ctypes
import subprocess
import urllib.request
import winreg

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 msg_box(text, title="Assistencia Remota"):
    ctypes.windll.user32.MessageBoxW(0, text, title, 0x40)

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

SERVER = "116.203.52.248"
KEY = "VoNciHfK04+8tqVDJH8gLs5CbsXpECQ4jBTuFPEt1XU="
RUSTDESK_URL = "https://github.com/rustdesk/rustdesk/releases/download/1.4.6/rustdesk-1.4.6-x86_64.exe"
RUSTDESK_BUNDLED = os.path.join(os.path.dirname(sys.argv[0]), "rustdesk-portable.exe")
# When bundled with PyInstaller, check sys._MEIPASS
if hasattr(sys, '_MEIPASS'):
    BUNDLED_RUSTDESK = os.path.join(sys._MEIPASS, "rustdesk-portable.exe")
    if os.path.exists(BUNDLED_RUSTDESK):
        RUSTDESK_BUNDLED = BUNDLED_RUSTDESK
DOWNLOAD_PATH = os.path.join(os.environ.get("TEMP", "C:\\Temp"), "Assistencia_Remota.exe")

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}'
"""

# RustDesk.toml (Config) - key_confirmed e um campo bool ao nivel raiz deste ficheiro.
CONFIG_TOML = f"""key_confirmed = true
"""

if not is_admin():
    run_as_admin()
    sys.exit(0)

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")
desktop = os.path.join(user_profile, "Desktop")

rustdesk_exe = os.path.join(os.environ.get("ProgramFiles", "C:\\Program Files"), "RustDesk", "rustdesk.exe")
alt_rustdesk = os.path.join(os.environ.get("ProgramFiles(x86)", "C:\\Program Files (x86)"), "RustDesk", "rustdesk.exe")
if not os.path.exists(rustdesk_exe) and os.path.exists(alt_rustdesk):
    rustdesk_exe = alt_rustdesk

already_installed = os.path.exists(rustdesk_exe)

ctypes.windll.user32.MessageBoxW(0, "Clique OK para comecar a instalacao.", "Assistencia Remota", 0x40)

subprocess.run(["taskkill", "/f", "/im", "rustdesk.exe"], capture_output=True)
subprocess.run(["taskkill", "/f", "/im", "RustDesk.exe"], capture_output=True)
subprocess.run(["taskkill", "/f", "/im", "RuntimeBroker_rustdesk.exe"], capture_output=True)
subprocess.run(["net", "stop", "RustDesk"], capture_output=True)
subprocess.run(["sc", "stop", "RustDesk"], capture_output=True)
time.sleep(3)

# Add Windows Defender exclusions
for excl_path in [r"C:\Program Files\RustDesk", os.path.join(os.environ.get("LOCALAPPDATA", ""), "rustdesk"), os.path.join(os.environ.get("APPDATA", ""), "RustDesk")]:
    try:
        subprocess.run(["powershell", "-Command", f"Add-MpPreference -ExclusionPath '{excl_path}'"], capture_output=True, timeout=10)
    except:
        pass

# ALWAYS uninstall and clean first
if already_installed:
    print("RustDesk encontrado. A desinstalar e reinstalar...")
    try:
        subprocess.run([rustdesk_exe, "--uninstall"], capture_output=True, timeout=15)
    except:
        pass
    time.sleep(3)

subprocess.run(["taskkill", "/f", "/im", "rustdesk.exe"], capture_output=True)
subprocess.run(["taskkill", "/f", "/im", "RustDesk.exe"], capture_output=True)
subprocess.run(["sc", "delete", "RustDesk"], capture_output=True)
time.sleep(2)

for d in [r"C:\Program Files\RustDesk", r"C:\Program Files (x86)\RustDesk"]:
    if os.path.exists(d):
        import shutil
        try:
            shutil.rmtree(d, ignore_errors=True)
        except:
            pass

for reg_path in [r"HKCU\Software\RustDesk", r"HKLM\Software\RustDesk", r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\RustDesk", r"HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\RustDesk"]:
    subprocess.run(["reg", "delete", reg_path, "/f"], capture_output=True)

already_installed = False

# Download or use bundled RustDesk
if os.path.exists(RUSTDESK_BUNDLED):
    print("A instalar a partir do ficheiro local...")
    INSTALL_PATH = RUSTDESK_BUNDLED
else:
    print("A descarregar...")
    try:
        urllib.request.urlretrieve(RUSTDESK_URL, DOWNLOAD_PATH)
    except Exception as e:
        msg_box(f"Erro ao descarregar: {e}\n\nVerifique a ligacao a internet.", "Assistencia Remota")
        sys.exit(1)
    INSTALL_PATH = DOWNLOAD_PATH

print("A instalar...")
process = subprocess.Popen([INSTALL_PATH, "--silent-install"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try:
    process.wait(timeout=60)
except subprocess.TimeoutExpired:
    process.kill()
    process.wait()

time.sleep(3)

if not os.path.exists(rustdesk_exe):
    process = subprocess.Popen([INSTALL_PATH, "--install"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    try:
        process.wait(timeout=60)
    except subprocess.TimeoutExpired:
        process.kill()
        process.wait()
    time.sleep(3)

if not os.path.exists(rustdesk_exe):
    process = subprocess.Popen([DOWNLOAD_PATH, "--install"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    try:
        process.wait(timeout=60)
    except subprocess.TimeoutExpired:
        process.kill()
        process.wait()
    time.sleep(3)

for reg_path in [r"HKCU\Software\RustDesk", r"HKLM\Software\RustDesk"]:
    subprocess.run(["reg", "delete", reg_path, "/f"], capture_output=True)

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

subprocess.run(["net", "stop", "RustDesk"], capture_output=True)
subprocess.run(["taskkill", "/f", "/im", "rustdesk.exe"], capture_output=True)
subprocess.run(["taskkill", "/f", "/im", "RustDesk.exe"], capture_output=True)
time.sleep(3)

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)
    except Exception as e:
        print(f"Erro ao escrever config em {d}: {e}")

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 Exception as e:
        print(f"Erro ao escrever registo: {e}")

# NOTA: os ficheiros RustDesk.toml / RustDesk2.toml ja foram escritos diretamente
# nas pastas de config acima - e esse o metodo fiável. O --import-config / --config
# tem condicoes (config mais antigo que o exe / requer servico) que falham aqui.
if os.path.exists(rustdesk_exe):
    # Stop service first
    subprocess.run(["net", "stop", "RustDesk"], capture_output=True)
    subprocess.run(["taskkill", "/f", "/im", "rustdesk.exe"], capture_output=True)
    time.sleep(2)

# Garantir que o servico arranca automaticamente com o Windows (unattended apos reboot)
subprocess.run(["sc", "config", "RustDesk", "start=auto"], capture_output=True)
subprocess.run(["net", "start", "RustDesk"], capture_output=True)

for desk in [desktop, os.path.join(os.environ.get("PUBLIC", "C:\\Users\\Public"), "Desktop")]:
    for name in ["RustDesk.lnk", "rustdesk.lnk", "RustDesk.url"]:
        p = os.path.join(desk, name)
        if os.path.exists(p):
            try:
                os.remove(p)
            except:
                pass

try:
    import win32com.client
    shell = win32com.client.Dispatch("WScript.Shell")
    shortcut = shell.CreateShortCut(os.path.join(desktop, "Assistencia Remota.lnk"))
    shortcut.Targetpath = rustdesk_exe
    shortcut.WorkingDirectory = os.path.dirname(rustdesk_exe)
    shortcut.Description = "Assistencia Remota"
    shortcut.Save()
except:
    bat_content = f'''@echo off\nstart "" "{rustdesk_exe}"\n'''
    with open(os.path.join(desktop, "Assistencia Remota.bat"), "w") as f:
        f.write(bat_content)

msg_box(
    "Instalado com sucesso!"
)