import os
import sys
import subprocess
import urllib.request
import urllib.error
import hashlib
import tempfile
import requests
from win32com.client import Dispatch

def sha256_checksum(filename, block_size=65536):
    sha256 = hashlib.sha256()
    with open(filename, 'rb') as f:
        for block in iter(lambda: f.read(block_size), b''):
            sha256.update(block)
    return sha256.hexdigest()

def download_file(url, save_path):
    try:
        print(f"Downloading from {url} ...")
        urllib.request.urlretrieve(url, save_path)
        print(f"Downloaded to {save_path}")
        return True
    except Exception as e:
        print(f"Download failed from {url}: {e}")
        return False

def get_latest_github_launcher_url():
    api_url = "https://api.github.com/repos/eldewrito2/ElDewritoLauncher/releases/latest"
    try:
        response = requests.get(api_url)
        response.raise_for_status()
        data = response.json()

        for asset in data.get("assets", []):
            if asset["name"].lower() == "launcher.exe":
                return asset["browser_download_url"]
    except Exception as e:
        print(f"Failed to fetch latest GitHub launcher: {e}")
        return None

def download_alterware_launcher(save_path):
    if os.path.exists(save_path):
        print("Launcher already exists locally.")

    urls = [
        "http://eldewrito.org/download/launcher.exe",  # fallback
    ]

    github_url = get_latest_github_launcher_url()
    if github_url:
        urls.insert(0, github_url)  # prioritize GitHub if available

    with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
        tmp_path = tmp_file.name

    for url in urls:
        if download_file(url, tmp_path):
            break
    else:
        print("All download attempts failed.")
        if os.path.exists(tmp_path):
            os.remove(tmp_path)
        sys.exit(1)

    if not os.path.exists(save_path):
        print("No local launcher found, installing new launcher...")
        os.replace(tmp_path, save_path)
        return True

    local_hash = sha256_checksum(save_path)
    new_hash = sha256_checksum(tmp_path)

    if local_hash == new_hash:
        print("Local launcher is up-to-date. No update needed.")
        os.remove(tmp_path)
        return False

    print("Newer launcher detected, updating...")
    os.replace(tmp_path, save_path)
    return True

def run_launcher(launcher_path, install_dir):
    install_dir = install_dir.rstrip("\\/")
    print("Launching ElDewrito launcher...")
    subprocess.run([
        launcher_path,
        "--bonus",
        "-u",
        "--path", install_dir
    ], check=True)

def create_shortcut(launcher_path, shortcut_name):
    start_menu_dir = os.path.join(os.environ["APPDATA"], "Microsoft", "Windows", "Start Menu", "Programs", "Steam")
    os.makedirs(start_menu_dir, exist_ok=True)
    shortcut_path = os.path.join(start_menu_dir, f"{shortcut_name}.lnk")

    print(f"Creating shortcut: {shortcut_path}")
    shell = Dispatch("WScript.Shell")
    shortcut = shell.CreateShortcut(shortcut_path)
    shortcut.TargetPath = launcher_path
    shortcut.WorkingDirectory = os.path.dirname(launcher_path)
    shortcut.IconLocation = launcher_path
    shortcut.Save()

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python update_eldewrito.py <install_path>")
        sys.exit(1)

    install_dir = sys.argv[1]
    if not os.path.isdir(install_dir):
        print("Invalid install directory:", install_dir)
        sys.exit(1)

    launcher_path = os.path.join(install_dir, "launcher.exe")

    should_run = download_alterware_launcher(launcher_path)
    create_shortcut(launcher_path, "Halo 3 Online - ElDewrito")

    if should_run:
        run_launcher(launcher_path, install_dir)
    else:
        print("Skipping launcher run since it's up-to-date.")
