#!/usr/bin/env python3
import sys, os
from db import register_package, load_db, save_db
from build import build_package, fetch_recipe, fetch_all_recipes, MANIFEST_CACHE_DIR, fetch_all

RECIPE_CACHE_DIR = "/var/lib/fempkg/repo"

def list_installed():
    db = load_db()
    for pkg, ver in db["installed"].items():
        print(f"{pkg}-{ver}")

def update_all():
    fetch_all()
    print("Recipe and manifest cache updated.")

def upgrade_packages(pkg=None):
    db = load_db()
    if pkg:
        recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkg}.recipe.py")
        if not os.path.exists(recipe_file):
            print(f"Recipe for {pkg} not found. Run `fempkg update` first.")
            return
        build_package(recipe_file)
    else:
        for pkgname in db["installed"]:
            recipe_file = os.path.join(RECIPE_CACHE_DIR, f"{pkgname}.recipe.py")
            if not os.path.exists(recipe_file):
                print(f"Recipe for {pkgname} missing, skipping.")
                continue
            try: build_package(recipe_file)
            except Exception as e:
                print(f"Failed to upgrade {pkgname}: {e}")

def uninstall_package(pkgname):
    manifest_path = os.path.join(MANIFEST_CACHE_DIR, f"{pkgname}.txt")
    if not os.path.exists(manifest_path):
        print(f"No manifest for {pkgname}, cannot uninstall safely. Run `fempkg update` first.")
        return

    with open(manifest_path) as f:
        files = [line.strip() for line in f if line.strip()]

    # Remove files/directories in reverse order (leaves first)
    for file in reversed(sorted(files)):
        try:
            if os.path.islink(file) or os.path.isfile(file):
                os.remove(file)
                print(f"Removed {file}")
            elif os.path.isdir(file):
                try:
                    shutil.rmtree(file)
                    print(f"Removed directory {file}")
                except Exception:
                    print(f"Directory {file} not empty or protected, skipping")
        except Exception as e:
            print(f"Failed to remove {file}: {e}")

    # Remove manifest
    try:
        os.remove(manifest_path)
    except Exception as e:
        print(f"Failed to remove manifest {manifest_path}: {e}")

    # Remove from DB
    db = load_db()
    if pkgname in db["installed"]:
        db["installed"].pop(pkgname)
        save_db(db)

    print(f"{pkgname} uninstalled.")


def help_menu():
    print("Usage: fempkg [list|register|install|update|upgrade|uninstall]")
    print("  list                     - list installed packages")
    print("  register <name> <ver>    - manually register package")
    print("  install <recipe.py>      - install from recipe")
    print("  update                   - update recipe+manifest cache")
    print("  upgrade <package>        - update all packages, optionally one")
    print("  uninstall <package>      - uninstall a package")

def main():
    if len(sys.argv) < 2:
        help_menu()
        return
    cmd = sys.argv[1]
    if cmd == "list": list_installed()
    elif cmd == "register" and len(sys.argv) == 4: register_package(sys.argv[2], sys.argv[3])
    elif cmd == "install" and len(sys.argv) >= 3:
        for pkgname in sys.argv[2:]:
            print(f"Installing {pkgname} …")
            recipe_file = fetch_recipe(pkgname)
            build_package(recipe_file)
            print(f"{pkgname} installed")
    elif cmd == "update" and len(sys.argv) == 2: update_all()
    elif cmd == "upgrade":
        if len(sys.argv) == 3: upgrade_packages(sys.argv[2])
        elif len(sys.argv) == 2: upgrade_packages()
        else: help_menu()
    elif cmd == "uninstall" and len(sys.argv) == 3: uninstall_package(sys.argv[2])
    else: help_menu()

if __name__ == "__main__":
    main()
