#!/usr/bin/env bash
set -euo pipefail

# FactoryOS Package Manager
# Downloads packages from the FactoryOS repository server

FACTORY_SERVER="repaa@192.168.0.111"
FACTORY_REPO_DIR="/srv/factory-repo"
FACTORY_SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=5"
FACTORY_CACHE="/var/cache/factory"

C_RED='\033[0;31m'
C_GREEN='\033[0;32m'
C_CYAN='\033[0;36m'
C_ORANGE='\033[38;5;208m'
C_BOLD='\033[1m'
C_RESET='\033[0m'

info()  { echo -e "${C_CYAN}[factory]${C_RESET} $*"; }
ok()    { echo -e "${C_GREEN}[factory]${C_RESET} $*"; }
err()   { echo -e "${C_RED}[factory]${C_RESET} $*" >&2; }
die()   { err "$@"; exit 1; }

usage() {
    cat <<EOF
${C_ORANGE}FactoryOS Package Manager${C_RESET}

Usage: factory <command> [arguments]

Commands:
  install <package(s)>     Install packages from the FactoryOS repo
  remove <package(s)>      Remove installed packages
  update <package(s)>      Update specific packages from the repo
  update all               Update all upgradable packages
  search <package>         Search for a package on the server
  list local               List locally installed packages
  list repo                List all packages available on the server
  sync                     Sync package database from server
  info <package>           Show info about a remote package

EOF
}

# ── Helpers ────────────────────────────────────────────────────────

factory_sync_db() {
    mkdir -p "$FACTORY_CACHE"
    info "Syncing package database from server..."
    ssh $FACTORY_SSH_OPTS "$FACTORY_SERVER" "ls ${FACTORY_REPO_DIR}/" 2>/dev/null > "$FACTORY_CACHE/db.list" || die "Cannot connect to FactoryOS repo server."
    ok "Database synced. $(wc -l < "$FACTORY_CACHE/db.list") packages available."
}

factory_search_db() {
    local query="$1"
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi
    grep -i "$query" "$FACTORY_CACHE/db.list" 2>/dev/null || true
}

factory_install_pkg() {
    local pkg="$1"
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi

    if ! grep -q "^${pkg}$" "$FACTORY_CACHE/db.list" 2>/dev/null; then
        err "Package '${pkg}' not found in FactoryOS repo."
        return 1
    fi

    mkdir -p "$FACTORY_CACHE"
    info "Downloading ${pkg} from server..."
    scp $FACTORY_SSH_OPTS "${FACTORY_SERVER}:${FACTORY_REPO_DIR}/${pkg}" "$FACTORY_CACHE/" 2>/dev/null \
        || die "Failed to download ${pkg}."

    local pkgfile
    pkgfile=$(find "$FACTORY_CACHE" -name "${pkg}*" -type f | head -1)
    if [[ -z "$pkgfile" ]]; then
        die "Downloaded file not found."
    fi

    info "Installing ${pkg}..."
    pacman -U --noconfirm "$pkgfile" 2>/dev/null || {
        err "Failed to install ${pkg}."
        return 1
    }
    ok "Installed ${pkg}."
}

factory_remove_pkg() {
    local pkg="$1"
    info "Removing ${pkg}..."
    pacman -R --noconfirm "$pkg" 2>/dev/null || {
        err "Failed to remove ${pkg}."
        return 1
    }
    ok "Removed ${pkg}."
}

factory_update_pkg() {
    local pkg="$1"
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi

    if ! grep -q "^${pkg}$" "$FACTORY_CACHE/db.list" 2>/dev/null; then
        err "Package '${pkg}' not found in FactoryOS repo."
        return 1
    fi

    mkdir -p "$FACTORY_CACHE"
    info "Downloading ${pkg} update from server..."
    scp $FACTORY_SSH_OPTS "${FACTORY_SERVER}:${FACTORY_REPO_DIR}/${pkg}" "$FACTORY_CACHE/" 2>/dev/null \
        || die "Failed to download ${pkg}."

    local pkgfile
    pkgfile=$(find "$FACTORY_CACHE" -name "${pkg}*" -type f | head -1)

    info "Updating ${pkg}..."
    pacman -U --noconfirm "$pkgfile" 2>/dev/null || {
        err "Failed to update ${pkg}."
        return 1
    }
    ok "Updated ${pkg}."
}

factory_update_all() {
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi

    info "Checking for updates..."
    local installed
    installed=$(pacman -Q 2>/dev/null | awk '{print $1}')
    local updated=0

    while IFS= read -r pkg; do
        if echo "$installed" | grep -qx "$pkg" 2>/dev/null; then
            info "Updating ${pkg}..."
            factory_update_pkg "$pkg" && ((updated++)) || true
        fi
    done < "$FACTORY_CACHE/db.list"

    if [[ $updated -eq 0 ]]; then
        ok "All FactoryOS packages are up to date."
    else
        ok "Updated ${updated} package(s)."
    fi
}

factory_list_repo() {
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi
    echo -e "${C_BOLD}Available packages in FactoryOS repo:${C_RESET}"
    cat "$FACTORY_CACHE/db.list"
}

factory_list_local() {
    echo -e "${C_BOLD}Installed packages:${C_RESET}"
    pacman -Q 2>/dev/null
}

factory_info_pkg() {
    local pkg="$1"
    if [[ ! -f "$FACTORY_CACHE/db.list" ]]; then
        factory_sync_db
    fi

    if ! grep -q "^${pkg}$" "$FACTORY_CACHE/db.list" 2>/dev/null; then
        err "Package '${pkg}' not found in FactoryOS repo."
        return 1
    fi

    info "Package: ${pkg}"
    ssh $FACTORY_SSH_OPTS "$FACTORY_SERVER" "cat ${FACTORY_REPO_DIR}/${pkg}/PKGINFO 2>/dev/null" 2>/dev/null || echo "  (no PKGINFO available)"
}

# ── Main ───────────────────────────────────────────────────────────

[[ $# -eq 0 ]] && { usage; exit 0; }

CMD="$1"
shift

case "$CMD" in
    install)
        [[ $# -eq 0 ]] && die "Usage: factory install <package(s)>"
        for pkg in "$@"; do
            factory_install_pkg "$pkg"
        done
        ;;
    remove)
        [[ $# -eq 0 ]] && die "Usage: factory remove <package(s)>"
        for pkg in "$@"; do
            factory_remove_pkg "$pkg"
        done
        ;;
    update)
        [[ $# -eq 0 ]] && die "Usage: factory update <package(s)> or factory update all"
        if [[ "$1" == "all" ]]; then
            factory_update_all
        else
            for pkg in "$@"; do
                factory_update_pkg "$pkg"
            done
        fi
        ;;
    search)
        [[ $# -eq 0 ]] && die "Usage: factory search <package>"
        factory_search_db "$1"
        ;;
    list)
        [[ $# -eq 0 ]] && die "Usage: factory list [local|repo]"
        case "${1:-}" in
            local) factory_list_local ;;
            repo)  factory_list_repo ;;
            *)     die "Usage: factory list [local|repo]" ;;
        esac
        ;;
    sync)
        factory_sync_db
        ;;
    info)
        [[ $# -eq 0 ]] && die "Usage: factory info <package>"
        factory_info_pkg "$1"
        ;;
    -h|--help|help)
        usage
        ;;
    *)
        err "Unknown command: ${CMD}"
        usage
        exit 1
        ;;
esac
