"""Bundle the browser app and install it in this user's Gotchi Local directory."""
import argparse
import json
import re
from pathlib import Path


def bundle(source):
    html = (source / "index.html").read_text(encoding="utf-8")
    for marker, name in (("/* FRONTIEROS_SDK */", "frontier-sdk.js"), ("/* FRONTIEROS_APP */", "app.js")):
        if html.count(marker) != 1:
            raise ValueError(f"Missing unique bundle marker: {marker}")
        script = (source / name).read_text(encoding="utf-8")
        if "</script" in script.lower():
            raise ValueError(f"Inline script contains a closing tag: {name}")
        html = html.replace(marker, script)
    return html


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--replace", action="store_true", help="Replace an existing app's source; preserve its stored data")
    args = parser.parse_args()
    source = Path(__file__).resolve().parent
    manifest = json.loads((source / "manifest.json").read_text(encoding="utf-8"))
    app_id = manifest["id"]
    if not isinstance(app_id, str) or not re.fullmatch(r"[a-z][a-z0-9-]{0,14}", app_id):
        parser.error("manifest id must start with a lowercase letter and use 1–15 lowercase letters, digits or hyphens")
    target = Path.home().resolve() / ".gotchi" / "mini-apps" / app_id
    if any(p.is_symlink() for p in (target, *target.parents)):
        parser.error("Refusing a symlink in the install path")
    if target.exists() and not args.replace:
        parser.error(f"{target} already exists; use --replace to update its source")
    html = bundle(source)
    target.mkdir(parents=True, exist_ok=True)
    files = (("manifest.json", json.dumps(manifest, indent=2) + "\n"), ("index.html", html))
    for name, _ in files:
        destination = target / name
        if destination.is_symlink():
            parser.error("Refusing a symlinked app file")
        temporary = target / (name + ".tmp")
        if temporary.exists() or temporary.is_symlink():
            parser.error(f"Remove the stale temporary file before retrying: {temporary}")
    for name, content in files:
        destination = target / name
        temporary = target / (name + ".tmp")
        with temporary.open("x", encoding="utf-8") as stream:
            stream.write(content)
        temporary.replace(destination)
    print(f"Installed {app_id} at {target}. Restart Gotchi Local, then open Mini apps.")


if __name__ == "__main__":
    main()
