import os
import json
import shutil
import requests
from globals import *
from pathlib import Path
from bs4 import BeautifulSoup
from urllib.parse import unquote

def download_directory(url, local_path:Path):
    response = requests.get(url)
    if response.status_code != 200:
        return -1

    for a in BeautifulSoup(response.text, "html.parser").find_all("a"):
        name:str = a['href']
        name = unquote(name)
        if name in ('.env', 'MudaeApps.lnk', 'Dashboard.py', 'Downloader.py', 'Start_Download.cmd', 'python-runtime.zip', '../'): continue

        full_url = url + name
        full_local = local_path / name

        if name.endswith("/"):
            if name == 'DashBoard/':
                download_directory(full_url, local_path.parent.parent)
            else:
                full_local.mkdir(parents=True, exist_ok=True)
                download_directory(full_url, full_local)
        else:
            if name == "MudaeAvatar.ico": stop_splash()
            full_local.parent.mkdir(parents=True, exist_ok=True)
            r = requests.get(full_url)
            if r.status_code == 200:
                with open(full_local, "wb") as f:
                    f.write(r.content)
            else:
                print(f"couldn't fetch {full_url}, status code {r.status_code}")
    return 1

def sync_apps_folder(APPS_FOLDER:Path, SERVER_URL):
    def nuke():
        print(f"updating the whole apps folder")
        if APPS_FOLDER.exists():
            shutil.rmtree(APPS_FOLDER)
        APPS_FOLDER.mkdir(parents=True, exist_ok=True)
        if int(download_directory(SERVER_URL, APPS_FOLDER)) < 0:
            raise ValueError("Invalid response from file server")
    
    version_server:dict = requests.get(SERVER_URL + "v").json()
    if (APPS_FOLDER / "version.json").exists():
        try:
            with open(APPS_FOLDER / "version.json", "r", encoding="utf-8") as f:
                version_local:dict = json.load(f)
        except:
            return nuke()
        with open(APPS_FOLDER / "version.json", "w", encoding="utf-8") as f:
            json.dump(version_server, f, indent=2, sort_keys=True)
            if version_local == version_server: return print("Skipped AppSync")
            else:
                changed_folders = set()
                all_keys = set(version_local.keys()) | set(version_server.keys())
                for path in all_keys:
                    if version_local.get(path) == version_server.get(path): continue
                    print(f"{path} has a different hash")
                    parts = path.split("/")
                    top_folder = parts[0]
                    changed_folders.add(top_folder)
                if changed_folders:
                    for folder in changed_folders:
                        print(f"updating {folder}")
                        if folder == "DashBoard":
                            local_folder = APPS_FOLDER.parent.parent
                        else:
                            local_folder = APPS_FOLDER / folder
                            if local_folder.exists():
                                shutil.rmtree(local_folder)
                            local_folder.mkdir(parents=True, exist_ok=True)
                        url_folder   = SERVER_URL + folder + "/"
                        if int(download_directory(url_folder, local_folder)) < 0:
                            raise ValueError("Invalid response from file server")
                    return
    nuke()